【问题标题】:CSRF with Spring and Angular 2带有 Spring 和 Angular 2 的 CSRF
【发布时间】:2017-02-19 22:23:58
【问题描述】:

我正在尝试使用 Spring Security (4.1.3) 和 Angular 2.0.1 实现 CSRF 保护

相关主题有很多来源,但我找不到明确的说明。有些陈述甚至相互矛盾。

我读到了 springs 的做法(尽管指南描述了 Angular 1 方式)Spring Security Guide with Angular 它意味着,与 .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

一切都应该“开箱即用”。 更进一步,angular guide to security 将 CSRF 保护描述为内置。

在我的环境中,POST 如下所示:

  • 有一个 OPTIONS 调用,它返回 POST、200 OK 和一个 XSRF-TOKEN - cookie。
  • 我的 http.post 添加了一个授权标头并添加了 RequestOption "withCredentials"
  • 它发送三个 cookie、两个 JSessionID 和一个 XSRF-TOKEN,它与 OPTIONS 调用收到的不同,没有 XSRF 标头。
  • 调试 Spring CsrfFilter 显示它会查找名为 X-XSRF-TOKEN 的标头并将其与名为 XSRF-TOKEN 的 cookie 中的令牌进行比较。

为什么 Angular 也不发送标头? 如果 Spring 只检查提供的 cookie 和提供的标头而没有任何服务器端操作,这如何安全?

有一些类似的问题,如this,但只有 0 票的答案似乎(对我)完全错误,因为据我了解,CSRF 必须对 cookie 验证进行服务器端检查。

This 问题仅提供有关如何更改 cookie 或标头名称的信息,如 here 所述

我在这里缺少什么?我怀疑 Spring Security 实现中是否存在错误,但我无法让它正常工作。

有什么想法吗?

后调用

login(account: Account): Promise<Account> {  


   let headers = new Headers({ 'Content-Type': 'application/json' });
    headers.append('X-TENANT-ID', '1');
    headers.append('Authorization', 'Basic ' + btoa(account.userName + ':' + account.password));
    let options = new RequestOptions({ headers: headers, withCredentials:true });
   return this.http.post(this.loginUrl, account, options).toPromise()
  .then(this.extractData)
  .catch(this.handleError)

}

Spring 安全配置

 [] csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

【问题讨论】:

    标签: java spring cookies angular


    【解决方案1】:

    问题在于应用程序路径。 Spring 可以选择在其管道中设置 cookie-path,但尚未发布。

    我必须为接受不同 cookie 路径的 CsrfTokenRepository 编写自己的实现。

    这些是相关的位:

    public final class CookieCsrfTokenRepository implements CsrfTokenRepository
    
    private String cookiePath;
    
     @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());
        // cookie.setPath(getCookiePath(request));
        if (this.cookiePath != null && !this.cookiePath.isEmpty()) {
            cookie.setPath(this.cookiePath);
        } else {
            cookie.setPath(getRequestContext(request));
        }
    
        if (token == null) {
            cookie.setMaxAge(0);
        } else {
            cookie.setMaxAge(-1);
        }
        if (cookieHttpOnly && setHttpOnlyMethod != null) {
            ReflectionUtils.invokeMethod(setHttpOnlyMethod, cookie, Boolean.TRUE);
        }
    
        response.addCookie(cookie);
    }
    
    public void setCookiePath(String path) {
        this.cookiePath = path;
    }
    
    public String getCookiePath() {
        return this.cookiePath;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-02-08
      • 2017-09-07
      • 2018-01-30
      • 2019-09-18
      • 2016-12-20
      • 2018-03-06
      • 2019-05-25
      • 1970-01-01
      • 2017-09-16
      相关资源
      最近更新 更多