据我所知,在 Spring+JavaScript 单页应用程序中,我们需要以某种方式将 CSRF token 发送到客户端。
推荐的方法是使用 CsrfHeaderFilter
如本 Spring guide 中所述.按照这种方法,当应用程序启动时,它会向服务器发送一个 GET 请求,从而获取 token 。
但是我看到在某些事件(例如登录或注销)下,Spring Security 会更改 token 。 CsrfHeaderFilter
提前出现,因此无法检测到更改。因此,我需要在此类事件之后发送另一个 GET 请求。
我尝试查看 Spring Security 代码以查找是否有办法将更改的 token 与这些登录或注销请求一起发送,以便保存另一个 GET 请求。但是,找不到办法。
想知道在登录、注销等之后发送一个虚拟的 GET 请求是否像我现在所做的那样,看起来是一个很好的解决方案。或者,也许有更好的方法?
如果目前没有办法避免这个多余的 GET 请求,我想知道这是否会成为 Spring Security 提出一些可能之后的事情的票。
最佳答案
遇到了关于 CookieCsrfTokenRepository 的类似情况。
我使用的应用程序具有通过 REST 服务登录的自定义实现。该服务内部有 httpServletRequest.logout() 调用(正如我所发现的)导致清除 XSRF-TOKEN cookie 作为响应:
Set-Cookie:XSRF-TOKEN=; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/ibdrs; Secure
如果答案中没有新的 XSRF-TOKEN 值,我有两个选择:
事实证明,可以通过以下方式实现第二种选择:
@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);
}
.csrf()
.csrfTokenRepository(CustomCookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
关于Spring单页应用程序: CSRF token changing silently after login,注销等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31654565/