首页 文章

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

提问于
浏览
7

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

我在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 Security过滤器,因此无法恢复上下文 .

通常的方法不起作用,但似乎身份验证信息在会话中的某个位置,也因为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...

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

2 回答

  • 6

    您遇到的问题是将异常转换为错误页面的 ExceptionTranslationFilter 出现在 SecurityContextPersistenceFilter 之前,它将认证从 SecurityContextRepository 拉出并将其放入 SecurityContextHolder . 请求完成后 SecurityContextPersistenceFilter 将信息从 SecurityContextHolder 中取回 .

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

    通常, ExceptionTranslationFilter 是最外层的过滤器,以避免任何异常未被翻译的风险 .

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

  • 6

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

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>
    

相关问题