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



我正在使用Spring Security 4.2.1来验证SpringMVC Web应用程序。我有一个非常难以捉摸的问题,有时似乎有效,有时却被打破(打破得比有效的多)。

问题如下:

  • 在尝试登录时,AuthenticationProvider会正确地对用户进行身份验证,我会在日志中看到身份验证成功(并且经过身份验证的用户拥有所需的所有权限等,我可以在日志中查看它们)。

  • 然后,该框架似乎为用户清除了SecurityContextHolder,当它试图加载登录页时,就好像它们根本没有经过验证一样

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

  • 异常是如果我先明确注销。如果我去注销地址,我似乎可以在那之后登录。

我已经查看了我的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";
}

这是我正在使用的基本登录表单(Thymelaf):

<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),它来自与上面日志相同的请求周期:

所有三个请求

如有任何帮助,我们将不胜感激。我确信我在做一些愚蠢的事情。我已经使用这个框架很多年了,甚至写了很多自定义组件,但这一次我彻底被难住了(1d以上的实验)。我可以提供任何其他文件或样本,如果他们有助于找到它的底部。

谢谢。

TRy添加http.csrf().disable();到您的代码。可能是CSRF过滤器拦截了您的请求。

我在您提供的日志中看到了筛选器调用。

最新更新