带有 Angular 4 的 .NET CORE API - cookie 令牌和请求令牌已交换

Bob*_* B. 4 asp.net-core x-xsrf-token angular

尝试使用 Angular 和 .NET CORE 实现 XSRF 时,我不断收到此消息:“提供的防伪令牌验证失败。cookie 令牌和请求令牌已交换。” 我在 Angular 和 API 中配置了相同的 cookie 和标头名称。谁有想法?

过程

Angular 首次调用此 API 方法以检索 cookie

    [HttpGet("startSession")]
    public async Task<IActionResult> StartSession()
    {
        AntiforgeryTokenSet tokens = this.antiForgery.GetAndStoreTokens(this.HttpContext);

        this.HttpContext.Response.Cookies.Append(this.options.Value.Cookie.Name, tokens.RequestToken, new CookieOptions { HttpOnly = false });

        return this.Ok(
            new
            {
                Success = true
            });
    }
Run Code Online (Sandbox Code Playgroud)

然后 Angular 拦截下一个 POST 请求并稍微覆盖默认的 XSRF 处理,因为我需要它为 HTTPS URL 工作

    // Override default Angular XSRF handling since it won't work for         
    absolute URLs and we have to prefix with "https://"
    // Source:https://github.com/angular/angular/blob/master/packages/common/http/src/xsrf.ts
    @Injectable()
    export class HchbHttpXsrfInterceptor implements HttpInterceptor {
    constructor(
    private tokenService: HttpXsrfTokenExtractor) {}

    intercept(req: HttpRequest<any>, next: HttpHandler): 
    Observable<HttpEvent<any>> {
    const headerName = 'X-XSRF-TOKEN';
    const lcUrl = req.url.toLowerCase();
    // Skip both non-mutating requests.
    // Non-mutating requests don't require a token
    // anyway as the cookie set
    // on our origin is not the same as the token expected by another origin.
    if (req.method === 'GET' || req.method === 'HEAD' ) {
         return next.handle(req);
    }
    const token = this.tokenService.getToken();

    // Be careful not to overwrite an existing header of the same name.
    if (token !== null && !req.headers.has(headerName)) {
       req = req.clone({headers: req.headers.set(headerName, token)});
    }
    return next.handle(req);
    }
    }
Run Code Online (Sandbox Code Playgroud)

Cor*_*liu 6

我遇到了同样的问题,我想我发现了问题。该options.Cookie.NameAddAntiforgery 必须是不同的比你手动设置使用cookie context.Response.Cookies.Append

尝试更改其中之一的名称,它会起作用。现在,您将使用options.Cookie.Name名称和tokens.RequestToken值覆盖生成的 cookie 。

您可以注意到开发人员工具中的差异。

  • 使用生成的默认令牌options.Cookie.Name标记为http only( HttpOnly = true)
  • 使用手动附加的令牌context.Response.Cookies.Append标记为HttpOnly = false

第二个是从 JS/Angular 读取的(您可以在 JS 中读取它,因为HttpOnly=false和 作为 ajax 请求中的标头发送并针对无法从 JS 读取的默认值进行验证)