会话超时会终止CSRF令牌,使后续记住我的工作流失败

时间:2015-06-19 15:34:24

标签: java spring spring-security

我有一个基于Spring Security和Spring MVC的Spring 4 Web应用程序。它包括CSRF保护,以及记住我功能。此后包括配置的相关部分。

<sec:http auto-config="true">
    <sec:intercept-url pattern="/public/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <sec:intercept-url pattern="/**" access="ROLE_USER" />
    <sec:access-denied-handler error-page="/403" />
    <sec:form-login
        login-page="/public/login"
        authentication-failure-url="/public/login?error"
        authentication-success-handler-ref="authenticationSuccessHandler"
        username-parameter="userName"
        password-parameter="password" />
    <sec:logout
        logout-url="/logout"
        logout-success-url="/public/login?logout"
        delete-cookies="JSESSIONID" />
    <sec:remember-me
        services-ref="rememberMeServices" key="***" />
    <sec:csrf />
</sec:http>

<bean id="securityService" class="custom UserDetailsService" />
<bean id="authenticationSuccessListener" class="custom ApplicationListener" />
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
    <property name="key" value="***" />
    <property name="userDetailsService" ref="securityService" />
    <property name="tokenRepository" ref="custom PersistentTokenRepository" />
    <property name="parameter" value="rememberMe" />
</bean>
<bean id="authenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    <property name="targetUrlParameter" value="targetUrl" />
</bean>

场景:用户打开POST表单并开始填写,接听电话或其他任何内容,会话超时,CSRF令牌无效,用户提交表单,并获得“拒绝访问”。我一直在浏览器中手动删除JSESSIONID cookie来测试这种情况(保留SPRING_SECURITY_REMEMBER_ME_COOKIE)。

期望:当会话超时时,记住我,开始验证用户,并成功处理请求。

问题:鉴于CSRF的性质和记住我,我的期望是合理的,还是从根本上有缺陷?推出我自己的CsrfTokenRepository实现,将令牌存储在数据库而不是会话中是否有意义?上述情景的普遍接受的方法是什么?

提前致谢。

1 个答案:

答案 0 :(得分:0)

您需要警告用户会话即将过期。

如果您的系统支持实体的草稿版本,则可以在会话超时之前自动保存草稿。

然后显示一个对话框,指示会话已超时,并且他们需要再次登录,或者至少单击刷新。为了获得良好的安全性,您应该将它们重定向到登录页面。

<script>

/* where n is the number of seconds until session times out on server */

window.setTimeout(function(){

  autoSaveCurrentForm();
  showWarning();

}, n);

</script>