Spring Security重定向到登录页面并在身份验证成功后终止会话

时间:2017-01-24 16:09:33

标签: java spring spring-mvc authentication spring-security

我使用Spring Security 4.2.1来验证SpringMVC webapp。我有一个非常难以捉摸的问题,似乎有时会起作用而且会被其他人破坏(比它更有效)。

问题如下:

  • 登录尝试后,AuthenticationProvider正确地对用户进行身份验证,我在日志中看到Authentication Success(并且Authenticated用户具有所需的所有权限等,我可以在日志中看到它们。)

  • 然后,框架似乎清除了用户的SecurityContextHolder,当它尝试加载着陆页时,就好像它们根本没有经过身份验证一样

  • 这当然会导致重定向回到登录页面。

  • EXCEPTION是我先显式注销的。如果我去登出地址,我似乎可以在那之后登录。

我查看了我的Spring Sec配置并将其中的内容更改了几天,但仍然得到了相同的结果。我对它失去了理智。

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .authorizeRequests()
            .antMatchers(
                "/link/go/*",
                "/pixel/download/*",
                "/favicon.ico",
                "/ping*").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/j_spring_security_check")
            .defaultSuccessUrl("/")
            .permitAll()
            .authenticationDetailsSource(new CustomAuthenticationDetailsSource())
            .and()
        .logout()
            .permitAll();
}

这是一个具有此行为的基本控制器:

@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/", method = RequestMethod.GET)
public String showIndex() {
    return "pages/index";
}

@RequestMapping(value = "/login", method = RequestMethod.GET)
public String showLogin(HttpServletRequest request, HttpServletResponse response) {
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    return "pages/login";
}

这是我使用的基本登录表单(Thymeleaf):

<form th:action="@{/j_spring_security_check}" method="post" autocomplete="off">
      <div class="group">
        <input type="text" id="username" name="username" autocomplete="off" required="required" /><span class="highlight"></span><span class="bar"></span>
        <label>Username</label>
        <div th:if="${param.error}" class="alert alert-error">    
            Invalid username and password.
        </div>
        <div th:if="${param.logout}" class="alert alert-success"> 
            You have been logged out.
        </div>
      </div>
      <div class="group">
        <input type="password" id="password" name="password" autocomplete="off" required="required" /><span class="highlight"></span><span class="bar"></span>
        <label>Password</label>
      </div>
      <div class="group">
        <input type="text" id="token" name="token" autocomplete="off" required="required" /><span class="highlight"></span><span class="bar"></span>
        <label>Tracker Token</label>
      </div>
      <button type="submit" class="button buttonBlue">Log in
        <div class="ripples buttonRipples"><span class="ripplesCircle"></span></div>
    </button>
</form>

这些是非常相关的日志(成功身份验证的循环,然后是会话破坏和访问拒绝)。我记录了大量的上下文,但我指出了关键部分(带*),这样你就不必太费力了。

2017-01-24 10:32:25,386 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.FilterChainProxy: /j_spring_security_check at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-01-24 10:32:25,386 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.FilterChainProxy: /j_spring_security_check at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-01-24 10:32:25,386 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository: HttpSession returned null object for SPRING_SECURITY_CONTEXT

*2017-01-24 10:32:25,386 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository: No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@1ff52ee9. A new one will be created.

2017-01-24 10:32:25,386 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.FilterChainProxy: /j_spring_security_check at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-01-24 10:32:25,386 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.header.writers.HstsHeaderWriter: Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@362f8994
2017-01-24 10:32:25,386 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.FilterChainProxy: /j_spring_security_check at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
2017-01-24 10:32:25,387 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.FilterChainProxy: /j_spring_security_check at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2017-01-24 10:32:25,387 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/j_spring_security_check'; against '/logout'
2017-01-24 10:32:25,387 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.FilterChainProxy: /j_spring_security_check at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'

*2017-01-24 10:32:25,387 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/j_spring_security_check'; against '/j_spring_security_check'
*2017-01-24 10:32:25,387 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter: Request is to process authentication
*2017-01-24 10:32:25,388 [http-nio-8080-exec-4] DEBUG org.springframework.security.authentication.ProviderManager: Authentication attempt using com.company.project.tracker.config.security.CustomAuthenticationProvider

2017-01-24 10:32:25,729 [http-nio-8080-exec-4] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory: Returning cached instance of singleton bean 'delegatingApplicationListener'
2017-01-24 10:32:25,729 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy: Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@473f5bae
2017-01-24 10:32:25,729 [http-nio-8080-exec-4] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory: Returning cached instance of singleton bean 'delegatingApplicationListener'
2017-01-24 10:32:25,729 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy: Delegating to org.springframework.security.web.csrf.CsrfAuthenticationStrategy@213137f3

*2017-01-24 10:32:25,730 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter: Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d7d972f2: Principal: com.company.project.tracker.config.security.Principal@50525059; Credentials: [PROTECTED]; Authenticated: true; Details: com.company.project.tracker.config.security.CustomAuthenticationDetailsSource$CustomAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: BFDA41C5C1883560BACC75BB353001CA; Granted Authorities: com.company.project.tracker.config.security.UserAuthority@78746e0b

2017-01-24 10:32:25,730 [http-nio-8080-exec-4] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory: Returning cached instance of singleton bean 'delegatingApplicationListener'

*2017-01-24 10:32:25,730 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler: Redirecting to DefaultSavedRequest Url: http://localhost:8080/tracker
*2017-01-24 10:32:25,730 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.DefaultRedirectStrategy: Redirecting to 'http://localhost:8080/tracker'
*2017-01-24 10:32:25,730 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository: SecurityContext 'org.springframework.security.core.context.SecurityContextImpl@d7d972f2: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d7d972f2: Principal: com.company.project.tracker.config.security.Principal@50525059; Credentials: [PROTECTED]; Authenticated: true; Details: com.company.project.tracker.config.security.CustomAuthenticationDetailsSource$CustomAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: BFDA41C5C1883560BACC75BB353001CA; Granted Authorities: com.company.project.tracker.config.security.UserAuthority@78746e0b' stored to HttpSession: 'org.apache.catalina.session.StandardSessionFacade@1ff52ee9
*2017-01-24 10:32:25,730 [http-nio-8080-exec-4] DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter: SecurityContextHolder now cleared, as request processing completed

我认为这是开始处理经过身份验证的请求的截止点(即一切都出错的地方)。

2017-01-24 10:32:25,733 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'

*2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository: No HttpSession currently exists
*2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository: No SecurityContext was available from the HttpSession: null. A new one will be created.

2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.header.writers.HstsHeaderWriter: Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@362f8994
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher: Request 'GET ' doesn't match 'POST /logout
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher: Request 'GET ' doesn't match 'POST /j_spring_security_check
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'

*2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.authentication.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-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.FilterChainProxy:  at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher: Request 'GET ' doesn't match 'POST /logout
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher: Checking match of request : ''; against '/link/go/*'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher: Checking match of request : ''; against '/pixel/download/*'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher: Checking match of request : ''; against '/favicon.ico'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher: Checking match of request : ''; against '/ping*'
2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor: Secure object: FilterInvocation: URL: ; Attributes: [authenticated]

*2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.access.intercept.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-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.access.vote.AffirmativeBased: Voter: org.springframework.security.web.access.expression.WebExpressionVoter@2cca1b0b, returned: -1
*2017-01-24 10:32:25,734 [http-nio-8080-exec-5] DEBUG org.springframework.security.web.access.ExceptionTranslationFilter: Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied

正如您所看到的,当它返回到'/'地址时,会话消失了,存储在会话中的原始正确对象被匿名身份验证对象替换,显然未经授权要去 '/'。我还提供了相应的响应和请求标头(通过chrome),它与上述日志的请求周期相同:

All Three Requests

非常感谢任何帮助。我确信我做的事情很愚蠢。我已经使用了这个框架多年,甚至编写了大量的自定义组件,但这个让我彻底难倒(1d +实验)。我可以提供任何其他文件或样本,如果它们有助于深入了解它。

感谢。

1 个答案:

答案 0 :(得分:0)

尝试添加http.csrf()。disable();你的代码。它可能是CSRF过滤器拦截您的请求。

我在您提供的日志中看到过滤器调用。