基本身份验证不适用于 XSRF 令牌拦截

问题描述

我正在实现一个简单的身份验证 API,该 API 配置了 Spring Boot 以通过 Basic Auth 访问。这是一个简单的 GET API,没有任何参数,仅用于强制浏览器触发身份验证窗口:

localhost:8080/api/auth

我从我的 Angular 7.3.10 项目中使用此 API,该项目服务于

localhost:4200

同时,我使用 anti-CSRF 保护,因此我处理所有 API 调用,以便为 X-XSRF-TOKEN 提供一个额外的标头。这是我的HttpInterceptor

export class CustomHttpInterceptor implements HttpInterceptor {
    constructor(private xsrftokenExtractor: HttpXsrftokenExtractor) {
    }

    intercept(req: HttpRequest<any>,next: HttpHandler): Observable<HttpEvent<any>> {
        if (req.url.startsWith(environment.apiUrl)) {
            // send request with credential options in order to be able to read cross-origin cookies
            req = req.clone({ withCredentials: true });

            // return XSRF-TOKEN in each request's header (anti-CSRF security)
            const headerName = 'X-XSRF-TOKEN';
            let token = this.xsrftokenExtractor.getToken() as string;
            if (token !== null && !req.headers.has(headerName)) {
                req = req.clone({ headers: req.headers.set(headerName,token) });
            }
        }
        return next.handle(req);
    }
}

现在,当我在我的 Angular 应用程序中调用 auth 端点时,我可以编写我的凭据,然后出现以下错误

Access to XMLHttpRequest at 'http://localhost:8080/api/auth' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

拦截添加 preflight 的请求时有一个 XSRF token 请求,并且此请求不包含 Basic Auth header,即使我正确提供了我的凭据:

preflight request part 1

preflight request part 2

现在,如果我从拦截器中删除添加 XSRF token 的部分,那么在我提供凭据后,身份验证请求将正常工作。当然它不需要 XSRF token,因为它是一个 GET 请求,但将来我需要同时使用 Basic Authanti-CSRF 保护与 {{1} } 调用,因此必须能够使两者都工作。有什么想法吗?

解决方法

根据我的评论:

这是由于服务器端的 CORS 配置造成的。 看起来 API 需要 OPTIONS 请求的凭据。但是,这些请求是由浏览器触发的,您无法修改它们以添加自定义标头,就像您在屏幕截图中看到的那样...因此您的服务器返回 401。

解决方案是修改 CORS 配置服务器端,以便 OPTIONS 请求不需要身份验证