1.添加依赖jar
<!-- spring security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- cas -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
</dependency>
2.extends WebSecurityConfigurerAdapter
注意:MyUserDetailsService implements UserDetailsService , AuthenticationUserDetailsService<CasAssertionAuthenticationToken>一定要实现AuthenticationUserDetailsService<CasAssertionAuthenticationToken>,cas服务器认证通过后会回调此接口的public UserDetails loadUserDetails(CasAssertionAuthenticationToken token)方法。
关键代码添加过滤器Filter链:
http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint(serviceProperties()));
// 单点注销的过滤器,必须配置在SpringSecurity的过滤器链中,如果直接配置在Web容器中,貌似是不起作用的。我自己的是不起作用的。
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
singleSignOutFilter.setCasServerUrlPrefix(this.casServerConfig.getHost());
http.addFilter(casAuthenticationFilter())
.addFilterBefore(logoutFilter(), LogoutFilter.class)
.addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class);
在application.properties添加:
security.cas.server.host = http://192.168.10.95:8080/cas
security.cas.server.login = ${security.cas.server.host}/login
security.cas.server.logout = ${security.cas.server.host}/logout
security.cas.service.host = http://192.168.10.95:8088
security.cas.service.login = /login
security.cas.service.logout = /logout
创建@Component
@ConfigurationProperties(prefix = "security.cas.server")
public class CasServerConfig类和@Component
@ConfigurationProperties(prefix = "security.cas.service")
public class CasServiceConfig 类
以下为实现代码:
package pit.security;
import java.util.ArrayList;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.crypto.password.MessageDigestPasswordEncoder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //启用方法验证
public class PitWebSecutiryConfig extends WebSecurityConfigurerAdapter{
@Bean
MyUserDetailsService myUserDetailsService(){
return new MyUserDetailsService();
}
@Resource
private DataSource dataSource;
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/js/**","/css/**","/login**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html").loginProcessingUrl("/login").permitAll()
// .defaultSuccessUrl("/")
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/login").invalidateHttpSession(true).deleteCookies("JSESSIONID")
.and()
.csrf().disable();
http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint(serviceProperties()));
// 单点注销的过滤器,必须配置在SpringSecurity的过滤器链中,如果直接配置在Web容器中,貌似是不起作用的。我自己的是不起作用的。
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
singleSignOutFilter.setCasServerUrlPrefix(this.casServerConfig.getHost());
http.addFilter(casAuthenticationFilter())
.addFilterBefore(logoutFilter(), LogoutFilter.class)
.addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class);
// http.antMatcher("/**");
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.userDetailsService(myUserDetailsService()).passwordEncoder(new MessageDigestPasswordEncoder("MD5"));
// auth.jdbcAuthentication().dataSource(dataSource)
// .usersByUsernameQuery("SELECT COM_NUM,LOWER(User_Password),User_Validity FROM UserT where COM_NUM= ?")
// .authoritiesByUsernameQuery("SELECT COM_NUM,RESOURCE FROM T_USER_RESOURCES WHERE COM_NUM= ?")
// .passwordEncoder(new MessageDigestPasswordEncoder("MD5"));
auth.authenticationProvider(casAuthenticationProvider());
}
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
// ArrayList<AuthenticationProvider> list=new ArrayList<AuthenticationProvider>();
// list.add(casAuthenticationProvider());
// return new ProviderManager(list);
return super.authenticationManagerBean();
}
@Autowired
private CasServerConfig casServerConfig;
@Autowired
private CasServiceConfig casServiceConfig;
@Bean
public ServiceProperties serviceProperties() {
ServiceProperties serviceProperties = new ServiceProperties();
serviceProperties.setService(this.casServiceConfig.getHost() + this.casServiceConfig.getLogin());
serviceProperties.setSendRenew(this.casServiceConfig.getSendRenew());
return serviceProperties;
}
@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
casAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
casAuthenticationFilter.setServiceProperties(serviceProperties());
casAuthenticationFilter.setFilterProcessesUrl(this.casServiceConfig.getLogin());
casAuthenticationFilter.setContinueChainBeforeSuccessfulAuthentication(false);
casAuthenticationFilter.setAuthenticationSuccessHandler(
new SimpleUrlAuthenticationSuccessHandler("/")
);
return casAuthenticationFilter;
}
@Bean
public CasAuthenticationEntryPoint casAuthenticationEntryPoint(ServiceProperties serviceProperties) {
CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
entryPoint.setLoginUrl(this.casServerConfig.getLogin());
entryPoint.setServiceProperties(serviceProperties);
return entryPoint;
}
@Bean
public Cas30ServiceTicketValidator cas30ServiceTicketValidator() {
return new Cas30ServiceTicketValidator(this.casServerConfig.getHost());
}
@Bean
public CasAuthenticationProvider casAuthenticationProvider() {
CasAuthenticationProvider provider = new CasAuthenticationProvider();
provider.setKey("casProvider");
provider.setServiceProperties(serviceProperties());
provider.setTicketValidator(cas30ServiceTicketValidator());
provider.setAuthenticationUserDetailsService(customUserDetailsService());
return provider;
}
@Bean
public AuthenticationUserDetailsService<CasAssertionAuthenticationToken> customUserDetailsService(){
return new MyUserDetailsService();
}
@Bean
public LogoutFilter logoutFilter() {
String logoutRedirectPath = this.casServerConfig.getLogout();
// + "?service=" +
// this.casServiceConfig.getHost();
LogoutFilter logoutFilter = new LogoutFilter(logoutRedirectPath, new SecurityContextLogoutHandler());
logoutFilter.setFilterProcessesUrl(this.casServiceConfig.getLogout());
return logoutFilter;
}
}
package pit.security;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import pit.dao.UserTMapper;
import pit.model.UserT;
@Component
public class MyUserDetailsService implements UserDetailsService , AuthenticationUserDetailsService<CasAssertionAuthenticationToken>{
@Autowired
private UserTMapper utMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
//对应的权限添加
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
UserT usert=utMapper.selectByComnum(username);
User user=new User(username, usert.getUserPassword().toLowerCase(), authorities);
return user;
}
@Override
public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
System.out.println("==========当前的用户名是:"+token.getName());
String username=token.getName();
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
//对应的权限添加
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
UserT usert=utMapper.selectByComnum(username);
User user=new User(username, usert.getUserPassword().toLowerCase(), authorities);
return user;
}
}
package pit.security;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "security.cas.server")
public class CasServerConfig {
private String host;
private String login;
private String logout;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getLogout() {
return logout;
}
public void setLogout(String logout) {
this.logout = logout;
}
}
package pit.security;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "security.cas.service")
public class CasServiceConfig {
private String host;
private String login;
private String logout;
private Boolean sendRenew = false;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getLogout() {
return logout;
}
public void setLogout(String logout) {
this.logout = logout;
}
public Boolean getSendRenew() {
return sendRenew;
}
public void setSendRenew(Boolean sendRenew) {
this.sendRenew = sendRenew;
}
}
参考文档:
https://www.jianshu.com/p/3c4a007b0dcc
https://blog.csdn.net/u010475041/article/details/79592661
https://blog.csdn.net/cl_andywin/article/details/53998986
https://blog.csdn.net/weixin_40295896/article/details/78021062
超时设置: