Cookie CsrfTokenRepository.withHttpOnlyFalse() 做什么以及何时使用它?

Faz*_*iqi 7 java spring csrf spring-security spring-boot

我现在正在尝试学习 Spring Security,并且我已经看到许多使用它的不同示例。我知道 CSRF 是什么,并且 Spring Security 默认启用它。我很想知道的是这种定制。

  .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
  .and()
  .authorizeRequests(request -> {
                request
                    .antMatchers("/login").permitAll()
                    .anyRequest()
                    ....more code
Run Code Online (Sandbox Code Playgroud)

.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())条线做了什么样的定制,什么时候适合使用。如果有人能提供一个简单的解释,我将不胜感激。

Pat*_*mil 10

CSRF 代表跨站请求伪造

它是一种与请求一起发送以防止攻击的令牌。为了使用Spring Security的CSRF保护,我们首先需要确保我们使用正确的HTTP方法任何修改状态(PATCHPOSTPUT,和DELETE-不是GET)。

使用 Spring CookieCsrfTokenRepository 的 CSRF 保护工作如下:

  • 客户端向服务器(Spring Boot Backend)发出 GET 请求,例如请求主页
  • Spring 发送GET请求的响应以及Set-cookie包含安全生成的 XSRF 令牌的标头
  • 浏览器使用 XSRF Token 设置 cookie
  • 在发送状态更改请求(例如 POST)时,客户端(可能是有角度的)将 cookie 值复制到 HTTP 请求标头
  • 请求与标头和 cookie 一起发送(浏览器自动附加 cookie)
  • Spring比较header和cookie的值,如果相同则接受请求,否则返回403给客户端

该方法withHttpOnlyFalse允许 angular 读取 XSRF cookie。确保 Angular 发出 XHR 请求并将withCreddentials标志设置为 true。


代码来自CookieCsrfTokenRepository

@Override
public CsrfToken generateToken(HttpServletRequest request) {
    return new DefaultCsrfToken(this.headerName, this.parameterName,
            createNewToken());
}

@Override
public void saveToken(CsrfToken token, HttpServletRequest request,
        HttpServletResponse response) {
    String tokenValue = token == null ? "" : 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));
    }
    if (token == null) {
        cookie.setMaxAge(0);
    }
    else {
        cookie.setMaxAge(-1);
    }
    cookie.setHttpOnly(cookieHttpOnly);
    if (this.cookieDomain != null && !this.cookieDomain.isEmpty()) {
        cookie.setDomain(this.cookieDomain);
    }

    response.addCookie(cookie);
}

@Override
public CsrfToken loadToken(HttpServletRequest request) {
    Cookie cookie = WebUtils.getCookie(request, this.cookieName);
    if (cookie == null) {
        return null;
    }
    String token = cookie.getValue();
    if (!StringUtils.hasLength(token)) {
        return null;
    }
    return new DefaultCsrfToken(this.headerName, this.parameterName, token);
}


public static CookieCsrfTokenRepository withHttpOnlyFalse() {
    CookieCsrfTokenRepository result = new CookieCsrfTokenRepository();
    result.setCookieHttpOnly(false);
    return result;
}
Run Code Online (Sandbox Code Playgroud)

你可以探索这里的方法

  • 答案有很多关于 CSRF 的内容,但它对回答 TO 最初的问题几乎没有帮助。 (4认同)
  • 它应该适用于所有客户端框架 Angular、React 等 (3认同)
  • `withHttpOnlyFalse` 使浏览器能够通过 javascript 代码读取 cookie。如果黑客注入一些代码并读取 cookie 的 XSRF 令牌,然后使用该 XSRF 令牌和 cookie 本身发送伪造的 http 请求,该怎么办?后端可能认为伪造的请求是非法的。 (2认同)