0

在过去的 7 个小时里,我一直在为此工作,但似乎无法取得任何进展。我正在尝试让我的 XSRF-TOKEN 可用于前端(Angular 6)。但是,它似乎永远不可用。当我在网络选项卡中执行分析并在“Cookie”下查看时,它似乎就在它所有的光辉中。但是,如果我使用 Angular 的 CookieService 并尝试检索它,则不会返回任何内容。

要记住的事情:

  1. 在我的本地机器上运行时,我能够取出 XSRF-TOKEN 并将其放置在未来的标头请求中。
  2. 当两个前端和后端(Spring-boot)托管在两个不同的主机上但在同一个域下时,就会出现此问题。例如:前端可以是frontend.home.com;后端可以是 backend.home.com。
  3. HttpOnly 设置为 False。
  4. Angular 的 withCredentials 属性也设置为 true。

对于如何处理这个看似微不足道但令人沮丧的问题,我真的很感激。

谢谢。

后端:

http.httpBasic()
    .authenticationEntryPoint(new AuthenticationFailureHandler())
    .and()
        .authorizeRequests()
        .antMatchers("List of URL").permitAll()
        .anyRequest().authenticated()
    .and()
        .csrf()
        .ignoringAntMatchers("List of API to ignore CSRF Token")
        .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
    .and()
        .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
http.logout()
    .permitAll()
    .logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK)));
}

@Autowired
private CsrfTokenRepository csrfTokenRepository() {
    HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
    repository.setHeaderName("X-XSRF-TOKEN");
    return repository;
}

前端:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let newHeaders: HttpHeaders = req.headers;

    let csrfToken = this.cookieService.get("XSRF-TOKEN");
    if (csrfToken === null || csrfToken === undefined) {
        newHeaders = newHeaders.append('X-XSRF-TOKEN', 'undefined');
    } else {
        newHeaders = newHeaders.append('X-XSRF-TOKEN', csrfToken);
    }

    const authReq = req.clone({headers: newHeaders, withCredentials: true});
    return next.handle(authReq);
}

此外,当我查看开发人员工具时,我看到了三个不同的领域。

  1. 主页
  2. backend.home.com(XSRF cookie 只能在这里找到,其他地方无法访问)
  3. 前端.home.com
4

1 回答 1

0

根据编辑和评论,您可能需要更改要在域上设置的 CSRF cookie 的 Cookiehome.com域,而不是backend.home.com仅在域上。您可以通过更改CookieCsrfTokenRepository

CookieCsrfTokenRepository repository = CookieCsrfTokenRepository.withHttpOnlyFalse();
repository.setCookieDomain("home.com");

http.httpBasic()
    .authenticationEntryPoint(new AuthenticationFailureHandler())
    .and()
        .authorizeRequests()
        .antMatchers("List of URL").permitAll()
        .anyRequest().authenticated()
    .and()
        .csrf()
        .ignoringAntMatchers("List of API to ignore CSRF Token")
        .csrfTokenRepository(repository)
    .and()
        .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
http.logout()
    .permitAll()
    .logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK)));
}

请参阅我上面写的存储库设置的前两行,然后用作令牌存储库。

于 2020-04-23T13:36:55.947 回答