我正在调整项目以使用Spring Security CSRF保护,而且我得到了一个有趣的行为。在我的登录页面上,如果我刷新页面一次,三次,五次等等,那么当我在其中放入适当的凭据时,由于CSRF失败而将我踢出去,但是如果我立即登录或者在两次,四次,六次等之后登录刷新,我接受了。
我在为什么会这样做方面取得了进展,但我无法弄清楚如何解决这个问题。似乎每个其他请求只生成一个新的CSRF令牌,即使每次请求都以新会话结束。潜入Spring逻辑表明,最有可能发生以下事件序列:
SaveOnAccessCsrfToken
的标记(T1),并将其添加为请求属性。SaveOnAccessCsrfToken
将令牌保存到会话中(S1)。DefaultCsrfToken
并将此(旧令牌 - T1)添加到请求中,而不是创建新请求。DefaultCsrfToken
,因此没有任何内容添加到会话中(S2)。SaveOnAccessCsrfToken
的新令牌(T2),并将其添加为请求属性。SaveOnAccessCsrfToken
将令牌保存到会话中(S3)。我似乎解决方案是在会话创建时更改,但我无法弄清楚如何做到这一点。想法?
使用Spring 4.2.2和Spring-Security 4.0.3
这是安全性XML:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<http pattern="/resources/**" security="none" />
<http pattern="/WEB-INF/**" security="none" />
<http pattern="/error/**" security="none" />
<!-- Other unrelated URLs -->
<!-- Configure Spring URL based Web Security -->
<http>
<intercept-url pattern="/login**" access="permitAll"/>
<!-- Other unrelated URLs -->
<intercept-url pattern="/**" access="isFullyAuthenticated()"/>
<form-login login-page="/login"
authentication-failure-url="/loginFailure?$general{login.fail.urlPostFix}"
default-target-url="/afterSuccessfulLogin"
login-processing-url="/j_spring_security_check" />
<logout delete-cookies="JSESSIONID"
invalidate-session="false"
logout-success-url="/login"
logout-url="/logout" />
<session-management invalid-session-url="/login?invalidSession=true" />
<access-denied-handler error-page="/denied" />
<headers disabled="true" />
</http>
<authentication-manager>
<authentication-provider user-service-ref="adminSecurityService">
<password-encoder ref="passwordEncoder"/>
</authentication-provider>
</authentication-manager>
<!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database -->
<beans:bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder" />