Spring 单页应用程序:CSRF 令牌在登录、注销等后静默更改 [英] Spring Single Page Application: CSRF token changing silently after login, logout etc

查看:15
本文介绍了Spring 单页应用程序:CSRF 令牌在登录、注销等后静默更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,在 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.

但我看到在诸如 loginlogout 之类的某些事件下,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 代码以查找是否有办法将更改的令牌与这些 loginlogout 请求一起发送,以便另一个 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:

  1. 在登录后立即发出虚拟获取请求以获取新的 XSRF-TOKEN(如 OP 建议的那样)

  1. 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:

  1. 制作我自己的CustomCookieCsrfTokenRepository 作为CookieCsrfTokenRepository 的副本(源代码是此处).如果它不是最终的,那么扩展它而不是复制就足够了.

  1. 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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆