【问题标题】:Spring's SecurityContextHolder.getContext().getAuthentication() returns null after RedirectView is used in HTTPS/SSL在 HTTPS/SSL 中使用 RedirectView 后 Spring 的 SecurityContextHolder.getContext().getAuthentication() 返回 null
【发布时间】:2013-06-01 21:47:50
【问题描述】:

我有一个在 Tomcat 上运行的典型 Spring MVC。将系统切换为在 HTTPS 上运行(在纯 HTTP 下一切正常)后,登录停止工作。原因是Spring的SecurityContextHolder.getContext().getAuthentication()对象在使用RedirectView后变成了null

我已经搜索过答案,我发现的唯一一个建议在viewResolver bean 设置中将属性redirectHttp10Compatible 设置为false。这没有帮助。

我还检查了在整个重定向过程中,我的会话 ID 保持不变并且连接保持安全,即它不是 http 和 https 之间更改的问题(至少据我所知),反之亦然。

可能是什么问题?

<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">


  <http auto-config="true">
    <intercept-url pattern="/**" requires-channel="https" />

    <intercept-url pattern="/index*" access="ROLE_USER"/>


    <intercept-url pattern="/dashboard*" access="ROLE_USER" requires-channel="https"/>  

    <intercept-url pattern="/login*" access="ROLE_GUEST, ROLE_ANONYMOUS, ROLE_USER"/>
    <intercept-url pattern="/signin*" access="ROLE_GUEST, ROLE_ANONYMOUS, ROLE_USER"/>
    <intercept-url pattern="/signup*" access="ROLE_GUEST, ROLE_ANONYMOUS, ROLE_USER"/>    


    <form-login login-page="/home" 
                default-target-url="/home" 
                authentication-failure-url="/home?authentication_error=true"
                authentication-success-handler-ref="redefineTargetURL"
    />


    <anonymous username="guest" granted-authority="ROLE_GUEST" key="anonymousKey"/>
    <logout invalidate-session="true" logout-success-url="/logout?message=Logout Successful" />

    </http>



<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="userDetailsService" />
</authentication-manager>


<beans:bean id="redefineTargetURL" class="com.groupskeed.common.RedefineTargetURL" />
<beans:bean id="userDetailsService" class="com.groupskeed.security.UserDetailsServiceImpl" />

【问题讨论】:

  • 您是否尝试过通过会话访问它?另外请发布您的配置以帮助进一步调试。我会查看 Session 和 SecurityContext 之间的身份验证附件。
  • 感谢您的回复。我应该发布哪些配置文件?
  • Spring 安全配置。如果您使用任何自定义类实现,这些也可能会有所帮助。
  • 在这里。身份验证后,用户被重定向到 /dashboard。正是在此重定向期间,Authentication 对象变为 null。
  • 嗯...需要一些时间来研究一下。也许我今晚能找到一些时间。一件可能有帮助的快速事情:我注意到您仅在仪表板上使用 HTTPS,这可能会对 Spring 使用的会话产生一些刺激,作为第一步,尝试使所有页面都需要 HTTPS,并查看问题是否仍然存在。 (在旁注中,至少登录也应该是 HTTPS,我更喜欢在登录 HTTPS 后保持所有页面访问,以保持会话数据加密并更安全)

标签: java spring tomcat https spring-security


【解决方案1】:

SecurityContextHolder.getContext().getAuthentication() 在重定向后变为 null 是正确的,因为它是线程绑定的。但它应该从会话中重新填充。因此尝试跟踪会话中的SPRING_SECURITY_CONTEXT 属性。下面是一些示例代码来获得一个想法:

HttpSession session = request.getSession(true);
System.out.println(session.getAttribute("SPRING_SECURITY_CONTEXT"));

在 Spring Security 文档中,有一个部分是关于 HTTPS/HTTP 切换如何搞砸会话的,也许其中某处暗示了您的问题。 http://static.springsource.org/spring-security/site/faq.html#d0e223

上面的常见问题解答导致对会话在您的应用程序中的处理方式进行检查。 我可能会开始研究 AuthenticationSuccessHandler 实现。 (如果您愿意,可以将其发布到您的问题中。)

有关如何在 Web 应用程序中处理安全上下文的更多详细信息,请参阅以下内容:(section 5.4 Authentication in a Web Application):http://static.springsource.org/spring-security/site/docs/3.0.x/reference/technical-overview.html

【讨论】:

  • 非常感谢!所以(我理解正确吗?) - 你是说我应该在会话中将 SecurityContext 对象设置为属性,然后在重定向后从那里拉出来,而不是从 SecurityContextHolder 拉出来?
  • 通常 Spring Security 应该自己做这件事。取决于你自己实现的部分功能可能会被破坏。尝试找出调试模式下的 securitycontext 发生了什么,并找出行为与文档中所述内容的衍生时刻。要缩短此过程:如果您自己填充 securityContext,您可能还必须将其附加到会话。
  • 这真的很有帮助!不幸的是不能投票给你的答案,它需要我没有的“声誉”:(
  • 所以本质上,现在每次使用重定向时,我都需要从 Spring Security Context 对象中拉取用户的数据,然后在 SecurityContext 上重新分配 Authentication……什么都没有,这不是很奇怪写在 Spring Security 文档中?另外,我不会在 HTTP 和 HTTPS 之间切换,我总是在 HTTPS 域中。
  • 在我的应用程序中 HttpSession session = request.getSession(true); sysout(session.getAttribute("SPRING_SECURITY_CONTEXT"));是 != null 但 SecurityContextHolder.getContext().getAuthentication() 是 null。
猜你喜欢
  • 2013-07-08
  • 2014-04-07
  • 2019-04-28
  • 2015-08-17
  • 2019-06-29
  • 2017-04-25
  • 1970-01-01
  • 2016-07-24
相关资源
最近更新 更多