Spring单页应用程序: CSRF token changing silently after login,注销等

标签 spring spring-mvc spring-security

据我所知,在 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 值,我有两个选择:
  • 登录后立即发出虚拟获取请求以获取新的 XSRF-TOKEN(如 OP 建议的那样)
  • 在同一登录响应中获取更新的 XSRF-TOKEN 而不是清除 cookie。

  • 事实证明,可以通过以下方式实现第二种选择:
  • 制作了我自己的 CustomCookieCsrfTokenRepository 作为 CookieCsrfTokenRepository 的副本(源代码是 here )。如果它不是最终的,那么扩展它而不是复制就足够了。
  • 将副本中所有出现的 CookieCsrfTokenRepository 更改为 CustomCookieCsrfTokenRepository
  • 用永远不会清除 cookie 的新版本替换了 saveToken 方法:
    @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 以使用新类:
    .csrf()
        .csrfTokenRepository(CustomCookieCsrfTokenRepository.withHttpOnlyFalse())
        .and()
    
  • 关于Spring单页应用程序: CSRF token changing silently after login,注销等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31654565/

    相关文章:

    Spring Boot OAuth2 手动创建新的 JWT token

    java - 无需身份验证的Spring安全授权

    java - Spring oAuth2并发请求死锁

    java - 我可以在 Spring 解析器中返回 RuntimeBeanReference 吗?

    mysql - spring data JPA - mysql - findById() 为空,除非之前调用了 findAll()

    java - spring 验证中的 jsr-303 在没有默认组的情况下验证

    spring-mvc - LDAP - 上下文源的 AD 用户名密码配置

    Java Spring Boot 配置标准

    java - 尝试将Spring MVC集成到现有的Jersey API中,每次都404

    java - 当 SpringSecurity 找不到传入 token 时,阻止 SpringSecurity 发送自动 401