Spring Security 注销和最大会话数

Posted

技术标签:

【中文标题】Spring Security 注销和最大会话数【英文标题】:Spring Security logout and Maximum sessions 【发布时间】:2017-05-16 17:37:56 【问题描述】:

我正在关注 Spring.io 指南中有关 Spring Security 的 this 教程。注销和登录功能工作正常,但是当我在WebSecurityConfigurerAdapter 中添加以下行时,它无法按预期工作。 (基本上,如果用户已经登录一个设备,我想阻止他从两个设备登录)

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter 
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        // The configuration as in the tutorial
        http
            .httpBasic().and()
            .authorizeRequests()
                .antMatchers("/index.html", "/home.html", "/login.html", "/").permitAll()
                .anyRequest().authenticated()
                .and()
            .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

      // Added this for session management  
      http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true)
    
 

如果您注销并尝试再次登录,则会出现问题,返回 401 并显示消息“身份验证失败:最大 此主体的会话数超过 1'。 然而,在AngularJs 应用程序中,这部分的注销 URL 被命中

self.logout = function() 
   $http.post('logout', ).finally(function() 
     $rootScope.authenticated = false;
     $location.path("/");
   );

为什么在这种情况下会话数没有重置?

怎样才能让它按预期工作?

Link to github code

调试模式下的 Spring Security 日志

2017-01-03 21:38:01.806 DEBUG 32624 --- [nio-8080-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/logout'; against '/error'
2017-01-03 21:38:01.806 DEBUG 32624 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /logout at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-01-03 21:38:01.806 DEBUG 32624 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /logout at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-01-03 21:38:01.807 DEBUG 32624 --- [nio-8080-exec-9] w.c.HttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@442b5a9f: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@442b5a9f: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_USER'
2017-01-03 21:38:01.807 DEBUG 32624 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /logout at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-01-03 21:38:01.807 DEBUG 32624 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /logout at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
2017-01-03 21:38:01.807 DEBUG 32624 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /logout at position 5 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
2017-01-03 21:38:01.807 DEBUG 32624 --- [nio-8080-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/logout'; against '/logout'
2017-01-03 21:38:01.807 DEBUG 32624 --- [nio-8080-exec-9] o.s.s.w.a.logout.LogoutFilter            : Logging out user 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@442b5a9f: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_USER' and transferring to logout destination
2017-01-03 21:38:01.807 DEBUG 32624 --- [nio-8080-exec-9] o.s.s.w.a.l.SecurityContextLogoutHandler : Invalidating session: DDC79F814F9ECD2A0192531E977D53C9
2017-01-03 21:38:01.807 DEBUG 32624 --- [nio-8080-exec-9] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]
2017-01-03 21:38:01.808 DEBUG 32624 --- [nio-8080-exec-9] o.s.s.web.util.matcher.OrRequestMatcher  : matched
2017-01-03 21:38:01.808 DEBUG 32624 --- [nio-8080-exec-9] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@e0735a1
2017-01-03 21:38:01.809 DEBUG 32624 --- [nio-8080-exec-9] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2017-01-03 21:38:01.809 DEBUG 32624 --- [nio-8080-exec-9] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/user'; against '/error'
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 5 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /user' doesn't match 'POST /logout
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 6 of 13 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'
2017-01-03 21:38:38.069 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 7 of 13 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 8 of 13 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 9 of 13 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 10 of 13 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.a.AnonymousAuthenticationFilter  : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 11 of 13 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.session.SessionManagementFilter  : Requested session ID DDC79F814F9ECD2A0192531E977D53C9 is invalid.
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 12 of 13 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.security.web.FilterChainProxy        : /user at position 13 of 13 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/user'; against '/index.html'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/user'; against '/home.html'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/user'; against '/login.html'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/user'; against '/'
2017-01-03 21:38:38.070 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /user; Attributes: [authenticated]
2017-01-03 21:38:38.071 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2017-01-03 21:38:38.071 DEBUG 32624 --- [io-8080-exec-10] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@6bd96c27, returned: -1
2017-01-03 21:38:38.072 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.a.ExceptionTranslationFilter     : Access is denied (user is anonymous); redirecting to authentication entry point

org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.1.3.RELEASE.jar:4.1.3.RELEASE]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-4.1.3.RELEASE.jar:4.1.3.RELEASE]

2017-01-03 21:38:38.073 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.util.matcher.AndRequestMatcher   : Trying to match using Ant [pattern='/**', GET]
2017-01-03 21:38:38.073 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request '/user' matched by universal pattern '/**'
2017-01-03 21:38:38.073 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.util.matcher.AndRequestMatcher   : Trying to match using NegatedRequestMatcher [requestMatcher=Ant [pattern='/**/favicon.ico']]
2017-01-03 21:38:38.073 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/user'; against '/**/favicon.ico'
2017-01-03 21:38:38.073 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.NegatedRequestMatcher  : matches = true
2017-01-03 21:38:38.073 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.util.matcher.AndRequestMatcher   : Trying to match using NegatedRequestMatcher [requestMatcher=MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@47099aec, matchingMediaTypes=[application/json], useEquals=false, ignoredMediaTypes=[*/*]]]
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.m.MediaTypeRequestMatcher      : httpRequestMediaTypes=[application/json, text/plain, */*]
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.m.MediaTypeRequestMatcher      : Processing application/json
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.m.MediaTypeRequestMatcher      : application/json .isCompatibleWith application/json = true
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.u.matcher.NegatedRequestMatcher  : matches = false
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.util.matcher.AndRequestMatcher   : Did not match
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.s.HttpSessionRequestCache        : Request not saved as configured RequestMatcher did not match
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.a.ExceptionTranslationFilter     : Calling Authentication entry point.
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] s.w.a.DelegatingAuthenticationEntryPoint : Match found! Executing org.springframework.security.web.authentication.HttpStatusEntryPoint@301fca8
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@e0735a1
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2017-01-03 21:38:38.074 DEBUG 32624 --- [io-8080-exec-10] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/user'; against '/error'
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 5 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /user' doesn't match 'POST /logout
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 6 of 13 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 7 of 13 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter  : Basic Authentication Authorization header found for user 'user'
2017-01-03 21:39:24.188 DEBUG 32624 --- [nio-8080-exec-1] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2017-01-03 21:39:24.189 DEBUG 32624 --- [nio-8080-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter  : Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@442b5a9f: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_USER
2017-01-03 21:39:24.189 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 8 of 13 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-01-03 21:39:24.189 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 9 of 13 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-01-03 21:39:24.189 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 10 of 13 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2017-01-03 21:39:24.189 DEBUG 32624 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@442b5a9f: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_USER'
2017-01-03 21:39:24.189 DEBUG 32624 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /user at position 11 of 13 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-01-03 21:39:24.189 DEBUG 32624 --- [nio-8080-exec-1] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy@2bf94401
2017-01-03 21:39:24.191 DEBUG 32624 --- [nio-8080-exec-1] o.s.s.w.session.SessionManagementFilter  : SessionAuthenticationStrategy rejected the authentication object

org.springframework.security.web.authentication.session.SessionAuthenticationException: Maximum sessions of 1 for this principal exceeded
    at org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy.allowableSessionsExceeded(ConcurrentSessionControlAuthenticationStrategy.java:153) ~[spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
    at org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy.onAuthentication(ConcurrentSessionControlAuthenticationStrategy.java:123) ~[spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]


2017-01-03 21:39:24.192 DEBUG 32624 --- [nio-8080-exec-1] .a.SimpleUrlAuthenticationFailureHandler : No failure URL set, sending 401 Unauthorized error
2017-01-03 21:39:24.192 DEBUG 32624 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@e0735a1
2017-01-03 21:39:24.192 DEBUG 32624 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2017-01-03 21:39:24.192 DEBUG 32624 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

【问题讨论】:

【参考方案1】:

您需要执行以下操作才能使其正常工作:

    根据https://github.com/spring-projects/spring-security/issues/3078,您需要明确提供会话注册表作为解决此问题的方法。(此步骤是可选的。我猜它已在最新版本中修复。如果功能没有不工作,那么你可以添加这一步。)

    Spring Security 需要注册 HttpSessionListener

您的最终代码应如下所示:

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected class SecurityConfiguration extends WebSecurityConfigurerAdapter 
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        // @formatter:off
        http
            .httpBasic();

        http
            .authorizeRequests()
                .antMatchers("/index.html", "/home.html", "/login.html", "/").permitAll()
                .anyRequest().authenticated()
                .and()
            .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
        // @formatter:on
        http
            .sessionManagement()
                .maximumSessions(1)
                    .maxSessionsPreventsLogin(true)
                    .sessionRegistry(sessionRegistry());
    


// Work around https://jira.spring.io/browse/SEC-2855
@Bean
public SessionRegistry sessionRegistry() 
    SessionRegistry sessionRegistry = new SessionRegistryImpl();
    return sessionRegistry;


// Register HttpSessionEventPublisher
@Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() 
    return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());

【讨论】:

以上是关于Spring Security 注销和最大会话数的主要内容,如果未能解决你的问题,请参考以下文章

带有 LDAP 注销的 Spring Security 无法删除会话

java spring boot / spring security(HttpSecurity)中的会话到期时如何自动注销

当用户注销时,Spring Security 从数据库中删除会话

Grails Spring Security 最大并发会话

Spring Security WebFlux 注销

您如何在 spring-security 中注销所有已登录的用户?