Spring SecurityContext在错误页面上返回null身份validation

我正在尝试为403(拒绝访问)和500(内部服务器错误)等错误编写自定义错误页面。 它们将从Velocity模板呈现,并使用用户的语言环境翻译所有消息。 身份validation和区域设置解析在应用程序中正常工作。

我在web.xml中设置了所需页面的位置,在webmvc-context.xml中我添加了requet-to-view controller via。

我遇到的问题是SecurityContextHolder.getContext()。getAuthentication()在错误页面视图中返回null。 看着我看到的日志:

06.10 14:42:26 DEBUG - context.HttpSessionSecurityContextRepository(HttpSessionSecurityContextRepository.java:351) - - SecurityContext stored to HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@ece7b0b7: Authentication: ... 06.10 14:42:26 DEBUG - context.SecurityContextPersistenceFilter(SecurityContextPersistenceFilter.java:89) - - SecurityContextHolder now cleared, as request processing completed 06.10 14:42:26 DEBUG - servlet.DispatcherServlet(DispatcherServlet.java:691) - - DispatcherServlet with name 'foo' processing GET request for [/foo/app/error/403.html] 

因此,无论是Spring还是Tomcat重定向到错误页面并且请求都已完成,因此上下文被清除。 并且新的“请求”不会经历Spring Securityfilter,因此无法恢复上下文。

通常的方法不起作用,但似乎认证信息在会话中的某个地方,也因为AbstractTemplateView记录以下内容:

 Exposing session attribute 'SPRING_SECURITY_CONTEXT' with value [org.springframework.security.core.context.SecurityContextImpl@edfbd958: Authentication: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@edfbd958... 

如何正确获取正常页面和错误页面的行为相同?

您遇到的问题是将ExceptionTranslationFilter转换为错误页面的ExceptionTranslationFilter位于SecurityContextPersistenceFilter之前,后者将身份validation从SecurityContextPersistenceFilter中提取出来并将其放入SecurityContextHolder 。 当请求完成时, SecurityContextPersistenceFilter将信息从SecurityContextHolder取出。

它清除SecurityContextHolder的原因是SecurityContextHolder通常是线程本地的,如果servlet容器要重用一个线程(大多数这样做),他们可能会意外地将这些凭据提供给其他人。

通常, ExceptionTranslationFilter是最外层的filter,以避免任何exception未被转换的风险。

最好的办法是编写一个自定义的ExceptionTranslationFilter ,它接收SecurityContextRepository (通常是你提到的HTTP会话)并通过SecurityContextRepository提供对Authentication访问,而不是SecurityContextHolder 。 请记住,如果用户未登录,则Authentication仍为空。

问题可能是springSecurityFilterChain没有拦截错误。 尝试在web.xml中更改映射

  springSecurityFilterChain /* REQUEST ERROR