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

Posted

技术标签:

【中文标题】Spring SecurityContext 在错误页面上返回空身份验证【英文标题】:Spring SecurityContext returning null authentication on error pages 【发布时间】:2011-09-12 10:39:53 【问题描述】:

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

我在 web.xml 中将位置设置为所需的页面,并在 webmvc-context.xml 中通过添加 requet-to-view 控制器。

我遇到的问题是 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...

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

【问题讨论】:

【参考方案1】:

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

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

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

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

【讨论】:

谢谢!我接受了你的回答,因为它给了我正确的输入:ExceptionTranslationFilter 是处理异常的人。它具有accessDeniedHandler 属性,默认情况下是AccessDeniedHandlerImpl 的一个实例。幸运的是,它有一个 errorPage 属性,并且文档指出,“作为一个‘前锋’,SecurityContextHolder 将保持填充状态。”我重新连接了我的 bean,它起作用了!【参考方案2】:

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

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

【讨论】:

这让它为我工作错误页面现在知道您是否登录

以上是关于Spring SecurityContext 在错误页面上返回空身份验证的主要内容,如果未能解决你的问题,请参考以下文章

在 SecurityContext 中找不到 Authentication 对象 - Spring 5

使用 Spring Security 时请求之间是不是共享 SecurityContext?

Spring Oauth2:在 SecurityContext 中找不到身份验证对象

Spring Security 如何跨 Web 应用程序请求在线程中管理 SecurityContext?

在 Bootstrap 期间 Spring 安全返回 null SecurityContext

使用 Spring Security 时,在 bean 中获取当前用户名(即 SecurityContext)信息的正确方法是啥?