版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010475041/article/details/79592661
4) Spring Boot + Spring Security集成CAS
预期效果:
1. 访问客户端时跳转到cas登录
2. 登录完后,展示默认的用户信息
3. 对cas用户进行用户映射
分支代码:https://github.com/grissomsh/cas/tree/1.x-integration-spring-boot
cas校验流程:
- 用户访问业务系统(client)
- 无权限时跳转到cas(服务端),并且携带参数为
service=${客户端url}
,所以我们看到登录页时浏览器路径为http://localhost:8080/login?service=http%3A%2F%2Flocalhost%3A8123%2Flogin
- 当用户在cas处登录完后,会颁发一个ticket带回client端,如
http://localhost:8123/login/cas?ticket=xxxxx
- 业务系统获取到ticket后,拿这个ticket请求cas获取对应的登录用户
- cas返回对应的用户信息,业务系统再对该用户进行身份映射再次认证,则完成本次登录
a. 项目搭建
pom.xml
<!--核心依赖-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
</dependency>
b. 项目配置
CasSecurityConfig.java
注意
casAuthenticationProvider()
方法创建的bean,该bean可以设置用户映射,正常来说,例如通过第三方github登录,这里返回的openid,是github的用户id,则需要对用户进行映射或做用户绑定,则在这里做手脚
//http://www.baeldung.com/spring-security-cas-sso
@Configuration
public class CasSecurityConfig {
//cas服务
@Value("${cas.server.url:http://localhost:8080}")
private String casServerUrl;
@Bean
public ServiceProperties serviceProperties() {
ServiceProperties serviceProperties = new ServiceProperties();
//本机服务,访问/login/cas时进行校验登录
serviceProperties.setService("http://localhost:8123/login/cas");
serviceProperties.setSendRenew(false);
return serviceProperties;
}
@Bean
@Primary
public AuthenticationEntryPoint authenticationEntryPoint(
ServiceProperties sP) {
CasAuthenticationEntryPoint entryPoint
= new CasAuthenticationEntryPoint();
//cas登录服务
entryPoint.setLoginUrl(casServerUrl + "/login");
entryPoint.setServiceProperties(sP);
return entryPoint;
}
@Bean
public TicketValidator ticketValidator() {
//指定cas校验器
return new Cas30ServiceTicketValidator(
casServerUrl);
}
//cas认证
@Bean
public CasAuthenticationProvider casAuthenticationProvider() {
CasAuthenticationProvider provider = new CasAuthenticationProvider();
provider.setServiceProperties(serviceProperties());
provider.setTicketValidator(ticketValidator());
//固定响应用户,在生产环境中需要额外设置用户映射
provider.setUserDetailsService(
s -> new User("auth-user", "123", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
provider.setKey("CAS_PROVIDER_LOCALHOST_8123");
return provider;
}
@Bean
public SecurityContextLogoutHandler securityContextLogoutHandler() {
return new SecurityContextLogoutHandler();
}
@Bean
public LogoutFilter logoutFilter() {
//退出后转发路径
LogoutFilter logoutFilter = new LogoutFilter(
casServerUrl + "/logout",
securityContextLogoutHandler());
//cas退出
logoutFilter.setFilterProcessesUrl("/logout/cas");
return logoutFilter;
}
@Bean
public SingleSignOutFilter singleSignOutFilter() {
//单点退出
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
singleSignOutFilter.setCasServerUrlPrefix(casServerUrl);
singleSignOutFilter.setIgnoreInitConfiguration(true);
return singleSignOutFilter;
}
//设置退出监听
@EventListener
public SingleSignOutHttpSessionListener singleSignOutHttpSessionListener(
HttpSessionEvent event) {
return new SingleSignOutHttpSessionListener();
}
}
WebSecurityConfig.java
注意,
1.casAuthenticationFilter()
创建的bean为核心,所以必须设置anthenticationManager,cas返回的ticket由他来校验
2. 由于设置的ServiceProperties
bean响应路径为/cas/login,所以权限配置处必须允许访问到,否则会出现死循环
3. 入口点为casAuthenticationEntryPoint
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private AuthenticationProvider authenticationProvider;
@Autowired
private SingleSignOutFilter singleSignOutFilter;
@Autowired
private LogoutFilter logoutFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
//所有都需要认证才能访问
//由于设置了验证filter访问为,/login/cas,所以必须通过验证,否则出现死循环
http
.authorizeRequests().antMatchers("/login/cas").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic().authenticationEntryPoint(authenticationEntryPoint)
.and()
.logout().logoutSuccessUrl("/logout")
.and()
.addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class).addFilterBefore(logoutFilter, LogoutFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(authenticationProvider);
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
//设置cas认证提供
return new ProviderManager(
Arrays.asList(authenticationProvider));
}
@Bean
public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties sp)
throws Exception {
//cas认证过滤器,当触发本filter时,对ticket进行认证
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setServiceProperties(sp);
filter.setAuthenticationManager(authenticationManager());
return filter;
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
}
b. 测试
- 启动sso-server
- 启动sso-integration-spring-boot
访问:http://localhost:8123/profile
采用默认帐号casuser/Mellon
登录完成后,响应映射用户auth-user
的相关数据