Spring Security logout and Maximum sessions

2020-02-29 01:12发布

I am following this tutorial on Spring Security in the Spring.io guides. The logout and login functions are working fine, but when I add the following line in the WebSecurityConfigurerAdapter it doesn't work as expected. (Basically, I want to prevent a user from login from two devices if he is already logged in in one)

@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)
    }
} 

The problem occurs if you logout and try to login again, a 401 is returned with the message 'Authentication Failed: Maximum sessions of 1 for this principal exceeded'. Yet the logout URL is hit on this part in the AngularJs app

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

Why isn't the number of sessions reset in this case?

What can be done to make it work as expected?

Link to github code

Spring Security logs in debug mode

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条回答
时光不老,我们不散
2楼-- · 2020-02-29 01:41

You need to do following things to make it work:

  1. According to https://github.com/spring-projects/spring-security/issues/3078, you need to provide the session registry explicitly as a workaround to this issue.(This step is optional. I am guessing it has been fixed in the latest version. If the functionality doesn't work then you can add this step.)

  2. Spring Security requires a HttpSessionListener to be registered.

Your final code should look something like this:

@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());
}
查看更多
登录 后发表回答