Spring单页应用程序:CSRF令牌在登录,注销等后无提示更改 [英] Spring Single Page Application: CSRF token changing silently after login, logout etc
问题描述
据我所知,在Spring + JavaScript单页应用程序中,我们需要以某种方式将CSRF令牌发送给客户端.
As I know, in a Spring+JavaScript single page application, we need to send the CSRF token to the client in some way.
建议的方法是拥有一个CsrfHeaderFilter
,如春季指南.按照这种方法,当应用程序启动时,它将向服务器发送GET请求,从而获取令牌.
A recommended way would be to have a CsrfHeaderFilter
as described in this Spring guide. Following this approach, when the application will start, it will send a GET request to the server, thus fetching the token.
但是我看到在某些情况下,例如 login 或 logout ,Spring Security会更改令牌. CsrfHeaderFilter
是预先出现的,因此无法检测到更改.因此,我需要在此类事件之后发送另一个GET请求.
But I see that under certain events like login or logout, Spring Security changes the token. CsrfHeaderFilter
comes beforehand, and so can't detect the change. Hence, I am needing to send another GET request following such events.
我尝试窥视Spring Security代码,以查找是否有一种方法可以将更改的令牌与这些 login 或 logout 请求一起发送,以便另一个GET请求已保存.但是,找不到方法.
I tried peeping at the Spring Security code to find if there would be a way to send the changed token along with these login or logout requests, so that another GET request is saved. But, could not find a way.
就像我现在所做的那样,我想知道在登录,注销等之后是否发送虚拟的GET请求,这似乎是一个不错的解决方案.或者,也许有更好的方法?
Liked to know if sending a dummy GET request after login, logout etc., as I am now doing, looks like a good solution. Or, maybe there is a better way?
如果当前没有办法避免这个冗余的GET请求,我想知道这是否成为Spring Security提出一些事情的票证,然后才有可能.
If there is currently no way to avoid this redundant GET request, I was wondering if this becomes a ticket for Spring Security to come up with something after which it would be possible.
推荐答案
了解关于CookieCsrfTokenRepository的类似情况.
Came across with the similar situation regarding CookieCsrfTokenRepository.
我研究的应用程序具有通过REST服务进行登录的自定义实现.该服务中有httpServletRequest.logout()调用(据我所知),该响应导致清除XSRF-TOKEN cookie作为响应:
The application I worked on has a custom implementation of login with via REST-service. The service has httpServletRequest.logout() call inside that (as I figured out) led to clearing of XSRF-TOKEN cookies in response:
Set-Cookie:XSRF-TOKEN=; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/ibdrs; Secure
答案中没有新的XSRF-TOKEN值,我有两个选择:
Without new XSRF-TOKEN value in the answer I had two options:
-
在登录后立即发出虚拟的get请求以获取新的XSRF-TOKEN(如OP所建议的那样)
Make a dummy get request to obtain new XSRF-TOKEN right after login (as the OP suggested)
在相同的登录响应中获取更新的XSRF-TOKEN,而不是清除cookie.
Get updated XSRF-TOKEN in the same login response instead of clearing cookie.
事实证明,第二种选择可以通过以下方式实现:
It turned out that the second option could be achieved by:
Made my own CustomCookieCsrfTokenRepository as the copy of CookieCsrfTokenRepository (the source code is here). If it wasn't final it would be sufficient to extend it instead of copying.
将副本中所有出现的CookieCsrfTokenRepository更改为CustomCookieCsrfTokenRepository
Changed all the occurrences of CookieCsrfTokenRepository to CustomCookieCsrfTokenRepository inside the copy
用永不清除cookie的新版本替换了saveToken方法:
Replaced saveToken method with new version that never clears the cookie:
@Override
public void saveToken(CsrfToken token, HttpServletRequest request,
HttpServletResponse response) {
if (token == null) {
token = generateToken(request);
}
String tokenValue = token.getToken();
Cookie cookie = new Cookie(this.cookieName, tokenValue);
cookie.setSecure(request.isSecure());
if (this.cookiePath != null && !this.cookiePath.isEmpty()) {
cookie.setPath(this.cookiePath);
} else {
cookie.setPath(this.getRequestContext(request));
}
cookie.setMaxAge(-1);
if (cookieHttpOnly && setHttpOnlyMethod != null) {
ReflectionUtils.invokeMethod(setHttpOnlyMethod, cookie, Boolean.TRUE);
}
response.addCookie(cookie);
}
将HttpSecurity配置为使用新类:
Configured HttpSecurity to use the new class:
.csrf()
.csrfTokenRepository(CustomCookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
这篇关于Spring单页应用程序:CSRF令牌在登录,注销等后无提示更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!