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

ASP.NET 8 Core Web API防伪令牌验证失败,请求解决CSRF防护问题

解决ASP.NET 8 Core Web API跨域场景下CSRF令牌无效问题

问题根源

跨域场景下,ASP.NET Core的防伪机制依赖Cookie存储的令牌标识与请求头携带的令牌值配对验证。你的配置缺少跨域凭证传递、Cookie适配跨域的设置,且手动验证逻辑未正确关联Cookie部分,导致令牌验证失败。

具体修复步骤

1. 配置CORS允许跨域凭证传递

在Program.cs中添加CORS策略,明确指定前端域名并允许携带Cookie:

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowFrontendOrigin", policy =>
    {
        policy.WithOrigins("https://your-frontend-domain.com") // 替换为实际前端域名,禁止用*
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials(); // 关键:允许跨域请求携带Cookie
    });
});

// 路由中间件之后启用CORS
app.UseRouting();
app.UseCors("AllowFrontendOrigin");
app.UseAuthorization();

2. 调整防伪服务配置适配跨域

修改AddAntiforgery配置,设置Cookie的SameSite属性为None(跨域必需),并确保Cookie安全策略符合HTTPS环境:

builder.Services.AddAntiforgery(options =>
{
    options.HeaderName = "X-CSRF-TOKEN";
    options.Cookie.SameSite = SameSiteMode.None; // 跨域场景下必须设置为None
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // HTTPS环境强制Secure(生产必需)
    options.Cookie.HttpOnly = false; // 无需HttpOnly,防伪令牌的Cookie仅用于验证配对
});

3. 修正API端的防伪验证逻辑

不要手动仅验证请求头,使用IAntiforgery服务验证整个请求上下文的令牌对(Cookie+请求头):

using Microsoft.AspNetCore.Antiforgery;

public class AdminController : ControllerBase
{
    private readonly IAntiforgery _antiforgery;

    public AdminController(IAntiforgery antiforgery)
    {
        _antiforgery = antiforgery;
    }

    [HttpGet("GetUserAndChannelCounts")]
    public async Task<IActionResult> GetUserAndChannelCounts()
    {
        // 验证整个请求的防伪令牌(自动关联Cookie与请求头)
        await _antiforgery.ValidateRequestAsync(HttpContext);

        // 业务逻辑示例
        var result = new { UserCount = 150, ChannelCount = 30 };
        return Ok(result);
    }
}

4. 前端AJAX请求调整

确保请求携带withCredentials以传递Cookie,并正确获取页面生成的防伪令牌:

// 获取页面中@Html.AntiForgeryToken()生成的令牌
const csrfToken = document.querySelector('input[name="__RequestVerificationToken"]').value;
const jwtToken = localStorage.getItem("jwtToken"); // 假设JWT存储在localStorage

$.ajax({
    url: "https://your-api-domain.com/api/Admin/GetUserAndChannelCounts",
    method: "GET",
    headers: {
        "X-CSRF-TOKEN": csrfToken,
        "Authorization": `Bearer ${jwtToken}`
    },
    xhrFields: {
        withCredentials: true // 关键:允许跨域请求携带Cookie
    },
    success: (data) => {
        console.log("获取数据成功:", data);
        // 渲染数据到页面
    },
    error: (xhr) => {
        console.error("请求失败:", xhr.responseText);
    }
});

关键注意事项

  • 禁止使用*作为CORS的Origin值,必须指定具体前端域名,否则AllowCredentials会失效。
  • 生产环境必须使用HTTPS,SameSite=None要求Cookie为Secure,否则浏览器会拒绝发送Cookie。
  • 若前端使用非jQuery的请求库(如Axios),需设置对应凭证携带配置(Axios中为withCredentials: true)。

内容的提问来源于stack exchange,提问作者Sayed Asad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 08:52:23