CSRF与Spring Security集成时,会话超时导致Spring MVC中的访问被拒绝
问题内容:
我在Spring MVC项目中将CSRF令牌与Spring Security集成在一起。一切都可以与CSRF令牌一起正常使用,令牌将从客户端发送到服务器端。
我已经更改了logout
流程,使其成为POST
发送CSRF令牌的方法,并且工作正常。
发生会话超时时,我遇到了问题,需要将其重定向到spring默认注销URL,但是它提供了Access Denied
该URL。
如何重写此行为。
我在安全性配置文件中包含以下行
<http>
//Other config parameters
<csrf/>
</http>
如果有人需要更多信息,请告诉我。
问题答案:
这个问题有点老了,但是答案总是有用的。
首先,这是会话支持的CSRF令牌的一个已知问题,如docs:CSRF Caveats-
Timeouts中所述
。
要解决此问题,请使用一些Javascript来检测即将到来的超时,使用与会话无关的CSRF令牌存储库或创建自定义AccessDeniedHandler
路由。我选择了后者:
配置XML:
<http>
<!-- ... -->
<access-denied-handler ref="myAccessDeniedHandler"/>
</http>
<bean id="myAccessDeniedHandler" class="package.MyAccessDeniedHandler">
<!-- <constructor-arg ref="myInvalidSessionStrategy" /> -->
</bean>
MyAccessDeniedHandler:
public class MyAccessDeniedHandler implements AccessDeniedHandler {
/* ... */
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exception)
throws IOException, ServletException {
if (exception instanceof MissingCsrfTokenException) {
/* Handle as a session timeout (redirect, etc).
Even better if you inject the InvalidSessionStrategy
used by your SessionManagementFilter, like this:
invalidSessionStrategy.onInvalidSessionDetected(request, response);
*/
} else {
/* Redirect to a error page, send HTTP 403, etc. */
}
}
}
另外,您可以将自定义处理程序定义为DelegatingAccessDeniedHandler
:
<bean id="myAccessDeniedHandler" class="org.springframework.security.web.access.DelegatingAccessDeniedHandler">
<constructor-arg name="handlers">
<map>
<entry key="org.springframework.security.web.csrf.MissingCsrfTokenException">
<bean class="org.springframework.security.web.session.InvalidSessionAccessDeniedHandler">
<constructor-arg name="invalidSessionStrategy" ref="myInvalidSessionStrategy" />
</bean>
</entry>
</map>
</constructor-arg>
<constructor-arg name="defaultHandler">
<bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/my_error_page"/>
</bean>
</constructor-arg>
</bean>