java - Spring Working sessionRegistry 不使用 CAS auth
问题描述
我正在使用 Spring Boot 2.1.6.RELEASE。
我需要使角色已更改的用户的会话到期。
我试图使用 sessionRegistry 但它不起作用,我不知道为什么......
这是我的 SecurityConfigurer 类:
/**
* Configuració de seguretat
*/
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
public static final String WEB = "\\/((?!api).*)";
public static final String API = "/api/**";
@Order(1)
@Configuration
public static class RestApiWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Resource(name = "restAuthenticationFilter")
private Filter restAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher(API)
.csrf().disable()
.antMatcher(API)
.addFilterBefore(restAuthenticationFilter, CsrfFilter.class)
.antMatcher(API)
.authorizeRequests()
.antMatchers(API).authenticated()
.and()
.antMatcher(API)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
;
}
}
@Order(2)
@Configuration
public static class ApplicacionWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
private final CasProperties casProperties;
private final AuthenticationUserDetailsService<CasAssertionAuthenticationToken> casUsuariDetailsService;
private final UserDetailsService usuariDetailsService;
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}
@Autowired
public ApplicacionWebSecurityConfigurerAdapter(
CasProperties casProperties,
AuthenticationUserDetailsService<CasAssertionAuthenticationToken> casUsuariDetailsService,
@Qualifier("casUserDetailsService")
UserDetailsService usuariDetailsService) {
this.casProperties = casProperties;
this.casUsuariDetailsService = casUsuariDetailsService;
this.usuariDetailsService = usuariDetailsService;
}
@Bean
public ServiceProperties serviceProperties() throws UnknownHostException {
ServiceProperties serviceProperties = new ServiceProperties();
serviceProperties.setService(getUrlWithHostName(casProperties.getValidateUrl()));
serviceProperties.setSendRenew(false);
return serviceProperties;
}
@Bean
public CasAuthenticationProvider casAuthenticationProvider() throws UnknownHostException {
CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
casAuthenticationProvider
.setAuthenticationUserDetailsService(casUsuariDetailsService);
casAuthenticationProvider.setServiceProperties(serviceProperties());
casAuthenticationProvider
.setTicketValidator(cas20ServiceTicketValidator());
casAuthenticationProvider.setKey("an_id_for_this_auth_provider_only");
return casAuthenticationProvider;
}
@Bean
public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
return new Cas20ServiceTicketValidator(casProperties.getReturnUrl());
}
@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
casAuthenticationFilter
.setAuthenticationManager(authenticationManager());
casAuthenticationFilter.setFilterProcessesUrl("/cas/login");
casAuthenticationFilter.setSessionAuthenticationStrategy(sessionControlAuthenticationStrategy());
return casAuthenticationFilter;
}
@Bean
public CasAuthenticationEntryPoint casAuthenticationEntryPoint() throws UnknownHostException {
CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
casAuthenticationEntryPoint.setLoginUrl(casProperties.getLoginUrl());
casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
return casAuthenticationEntryPoint;
}
@Bean
public ConcurrentSessionControlAuthenticationStrategy sessionControlAuthenticationStrategy() {
ConcurrentSessionControlAuthenticationStrategy csas = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
csas.setMaximumSessions(1);
csas.setExceptionIfMaximumExceeded(true);
return csas;
}
/*
* User impersonation
*/
@Bean
public SwitchUserFilter switchUserFilter() {
SwitchUserFilter filter = new SwitchUserFilter();
filter.setUserDetailsService(usuariDetailsService);
filter.setSwitchUserUrl("/login/impersonate");
filter.setExitUserUrl("/logout/impersonate");
filter.setTargetUrl("/");
filter.setUsernameParameter("username");
filter.setSwitchFailureUrl("/");
return filter;
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(casAuthenticationProvider());
}
@Bean
public Filter ajaxTimeOutRedirectFilter() {
AjaxTimeoutRedirectFilter f = new AjaxTimeoutRedirectFilter();
f.setCustomSessionExpiredErrorCode(HttpStatus.UNAUTHORIZED.value());
return f;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// Afegim el filtre del cas a les peticions
http.addFilter(casAuthenticationFilter());
http
.regexMatcher(WEB)
.exceptionHandling().authenticationEntryPoint(
casAuthenticationEntryPoint())
.and()
.addFilterAfter(ajaxTimeOutRedirectFilter(), ExceptionTranslationFilter.class)
;
http
.regexMatcher(WEB)
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.regexMatcher(WEB)
.authorizeRequests()
.antMatchers("/images/**", "/css/**", "/fonts/**", "/js/**", "/bower_components/**").permitAll()
.antMatchers("/logout").permitAll()
.antMatchers("/cas/login").permitAll()
.antMatchers("/login/impersonate").hasRole("ADMIN")
// Actuator
.antMatchers("/health").permitAll()
.antMatchers("/info").permitAll()
.antMatchers("/actuator").permitAll()
// Swagger
.antMatchers("/swagger-resources/**",
"/v2/api-docs", "/webjars/**", "/swagger-ui.html").permitAll()
// Resta
.regexMatchers(WEB).authenticated()
;
http
.regexMatcher(WEB)
.logout().logoutUrl("/logout").deleteCookies("JSESSIONID")
.logoutSuccessUrl(getUrlWithHostName(casProperties.getLogoutUrl()))
.invalidateHttpSession(true);
http
.regexMatcher(WEB)
.headers().frameOptions().sameOrigin();
}
private String getUrlWithHostName(String urlToFormat) throws UnknownHostException {
return MessageFormat.format(urlToFormat, InetAddress
.getLocalHost().getCanonicalHostName());
}
}
}
我已经尝试了很多,但似乎注册表总是空的,并且主体和会话总是返回一个空映射......
有什么建议吗?谢谢
解决方案
似乎 ConcurrentSessionAuthenticationStrategy 还需要一个RegisterSessionAuthenticationStrategy,如 Cyril Gabis 在这里的回答中所述:SAML 身份验证的用户不会出现在 Spring Security 的 SessionRegistry 中。以下对我有用:
@Bean
public SessionAuthenticationStrategy sessionAuthenticationStrategy() {
List<SessionAuthenticationStrategy> strategies = new ArrayList<>();
ConcurrentSessionControlAuthenticationStrategy concurrentStrategy =
new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
concurrentStrategy.setMaximumSessions(1);
concurrentStrategy.setExceptionIfMaximumExceeded(true);
RegisterSessionAuthenticationStrategy registerStrategy =
new RegisterSessionAuthenticationStrategy(sessionRegistry());
strategies.add(concurrentStrategy);
strategies.add(registerStrategy);
return new CompositeSessionAuthenticationStrategy(strategies);
}
总之:
- 创建 SessionRegistry bean
- 创建 SessionAuthenticationStrategy bean
- 向 CasAuthenticationFilter 注册 SessionAuthenticationStrategy bean(或者在使用 SAML 时,SAMLProcessingFilter)。
会话注册 bean:
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
使用 CasAuthenticationFilter 注册它:
@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
casAuthenticationFilter.setAuthenticationManager(authenticationManager());
casAuthenticationFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy());
return casAuthenticationFilter;
}
推荐阅读
- c++ - 将纹理传递给 GLSL 着色器而不使用统一?
- hibernate - 在 Hibernate 环境中处理多对一关系实体中审计修订的最佳方法是什么?
- javascript - 使用字典将返回的状态映射到选择下拉列表以进行过滤,产生我试图删除的重复项并将唯一键附加到
- javascript - 如果 ImmerJS 是纯 javascript,它是如何“强类型化”的?
- javascript - 从嵌套的对象数组中返回匹配项
- radio - 我在哪里连接 433MHz 接收器 PCB 上的同轴电缆屏蔽层?
- sql - 如何根据它们的模式以透视方式显示所有数据库表
- node.js - 在 MacOS 上安装 Ghost:“ghost install local”在安装过程中产生“响应代码 401(未经授权)”
- macos - WKWebView 加载 HTML 和 Javascript 但无法加载 CSS 文件
- javascript - CodeHow to call ng-blur before ng-click for Mobile browsers