You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core WebAPI CSRF验证失败:未识别自定义请求头令牌

解决ASP.NET Core WebAPI CSRF验证不通过问题

登录认证后,后端将CSRF令牌存入XSRF-TOKEN Cookie,前端获取后在后续请求头中添加X-XSRF-TOKEN,但验证始终失败,系统持续检查.AspNetCore.Antiforgery.xxx Cookie,而非传入的请求头令牌。

后端中间件代码

public class CsrfValidationMiddleware
{
    private readonly IAntiforgery _antiforgery;
    private readonly RequestDelegate _next;

    public CsrfValidationMiddleware(RequestDelegate next, IAntiforgery antiforgery)
    {
        _next = next ?? throw new ArgumentNullException(nameof(next));
        _antiforgery = antiforgery ?? throw new ArgumentNullException(nameof(antiforgery));
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var isGetRequest = string.Equals("GET", context.Request.Method, StringComparison.OrdinalIgnoreCase);

        if (context.Request.Path == "/v1/api/login")
        {
            // Obtain and store anti-forgery tokens, including setting the cookie
            var antiforgeryTokens = _antiforgery.GetAndStoreTokens(context);

            // Access the CSRF token
            var csrfToken = antiforgeryTokens.RequestToken;

            // Add CSRF token to response headers
            context.Response.Cookies.Append("XSRF-TOKEN", csrfToken, new CookieOptions
            {
                HttpOnly = false,
                SameSite = SameSiteMode.None, // Adjust based on your requirements
                Secure = true // If your site is served over HTTPS
            });
        }

        // Validate anti-forgery token for non-GET requests
        if (!isGetRequest && context.Request.Path != "/v1/api/login")
        {
            await _antiforgery.ValidateRequestAsync(context);
        }

        // Call the next middleware in the pipeline
        await _next(context);
    }
}

React TypeScript请求代码

static api() {
    const jwtToken = localStorage.getItem('token')
    let token = Cookies.get("XSRF-TOKEN");
    console.log('maq',token)

    return axios.create({
      baseURL: process.env.BaseASE_URL, 
      headers: {
        'Access-Control-Allow-Origin': '*',
        'Content-Type': 'application/json',
        Authorization: 'Bearer ' + jwtToken,
        'X-XSRF-TOKEN':localStorage.getItem('csrf')
      }
    })
}

问题原因及解决方案

1. 核心原因

ASP.NET Core Antiforgery默认使用自有命名的Cookie(.AspNetCore.Antiforgery.xxx)和请求头(RequestVerificationToken),你的代码中手动设置了XSRF-TOKEN Cookie,但Antiforgery并未被配置为使用这些自定义名称,导致验证时仍在查找默认Cookie。

2. 具体修复步骤

(1)配置Antiforgery自定义名称

在Program.cs(或Startup.cs)中添加Antiforgery配置,指定要使用的Cookie和请求头名称:

builder.Services.AddAntiforgery(options =>
{
    // 指定Cookie名称为XSRF-TOKEN
    options.Cookie.Name = "XSRF-TOKEN";
    // 指定请求头名称为X-XSRF-TOKEN
    options.HeaderName = "X-XSRF-TOKEN";
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.Cookie.SameSite = SameSiteMode.None;
    options.Cookie.HttpOnly = false;
});

(2)简化中间件逻辑

GetAndStoreTokens方法会根据上述配置自动设置XSRF-TOKEN Cookie,无需手动调用Append,避免重复设置:

if (context.Request.Path == "/v1/api/login")
{
    var antiforgeryTokens = _antiforgery.GetAndStoreTokens(context);
    // 可选:将令牌添加到响应头,方便前端直接获取
    context.Response.Headers.Append("X-CSRF-TOKEN", antiforgeryTokens.RequestToken);
}

(3)修复前端请求代码

  • 直接从Cookie读取XSRF-TOKEN,而非从localStorage取未存储的csrf值
  • 开启withCredentials: true,确保浏览器携带Cookie到后端
  • 移除不必要的Access-Control-Allow-Origin请求头(这是后端响应头字段)
static api() {
    const jwtToken = localStorage.getItem('token');
    const xsrfToken = Cookies.get("XSRF-TOKEN");

    return axios.create({
        baseURL: process.env.BaseASE_URL, 
        headers: {
            'Content-Type': 'application/json',
            Authorization: jwtToken ? `Bearer ${jwtToken}` : '',
            'X-XSRF-TOKEN': xsrfToken || ''
        },
        withCredentials: true // 必须开启,否则浏览器不发送Cookie
    });
}

(4)跨域环境补充配置

如果前后端存在跨域,需在后端Cors配置中允许携带凭证:

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowFrontend", policy =>
    {
        policy.WithOrigins("你的前端域名") // 替换为实际前端域名
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials(); // 必须允许凭证传递
    });
});

// 在中间件管道中启用Cors(需放在UseRouting之后,UseAuthorization之前)
app.UseCors("AllowFrontend");

内容的提问来源于stack exchange,提问作者Maq Na

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 15:35:05