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

.NET 8 WASM+AspNetCore托管项目Antiforgery令牌配置异常求助

.NET 8 WASM + AspNetCore 托管项目 Antiforgery 令牌问题解决方案

问题1:首次初始化/GET请求时Antiforgery令牌Cookie未自动设置

原因

默认情况下,ASP.NET Core的Antiforgery中间件不会主动为GET请求生成并下发令牌——其核心设计是保护修改型HTTP请求(POST/PUT/DELETE等),无显式触发时不会自动生成令牌。仅靠UseAntiforgery()和AutoValidateAntiforgeryTokenAttribute配置,无法让GET请求自动触发令牌生成流程。

问题2:手动设置令牌后POST请求返回Bad Request

常见原因

  1. 请求头未携带Request Token:仅携带Cookie不足以通过验证,需将XSRF-TOKEN的值放到指定请求头中(需和服务端配置的头名称一致)。
  2. Antiforgery配置不统一:服务端与客户端的令牌头名称、Cookie属性(如Secure、SameSite)未对齐。
  3. HTTPS环境Cookie配置缺失:本地HTTPS场景下,Cookie未设置Secure = true,可能被浏览器拦截无法携带。

正确配置步骤

服务端配置(Program.cs)

显式统一Antiforgery的头名称、Cookie属性,并添加初始化令牌的GET接口:

builder.Services.AddAntiforgery(options =>
{
    // 指定前端携带令牌的请求头名称
    options.HeaderName = "X-XSRF-TOKEN";
    // HTTPS环境下强制Cookie使用Secure属性
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.Cookie.HttpOnly = true;
    options.Cookie.SameSite = SameSiteMode.Lax;
});

builder.Services.AddControllersWithViews(options =>
{
    // 全局启用Antiforgery验证,默认会跳过GET请求
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});

app.UseRouting();
// 必须在UseRouting之后、MapControllers之前调用
app.UseAntiforgery();

// 添加初始化令牌的GET接口,供客户端启动时调用
app.MapGet("/api/antiforgery/token", (HttpContext context, IAntiforgery antiforgery) =>
{
    var tokenSet = antiforgery.GetAndStoreTokens(context);
    // 下发可被JS读取的XSRF-TOKEN Cookie,用于前端获取请求头值
    context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!, new CookieOptions
    {
        HttpOnly = false,
        Secure = true,
        SameSite = SameSiteMode.Lax,
        Expires = DateTimeOffset.UtcNow.AddHours(1)
    });
    return Results.Ok();
});

app.MapControllers();
app.Run();

客户端(WASM)配置

  1. 应用启动时调用初始化接口获取令牌:
// 在Program.cs或主页面初始化逻辑中执行
var httpClient = builder.Services.GetRequiredService<HttpClient>();
await httpClient.GetAsync("/api/antiforgery/token");
  1. 配置HttpClient自动携带令牌头:
builder.Services.AddScoped(sp =>
{
    var client = new HttpClient
    {
        BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
    };

    // 从浏览器Cookie读取XSRF-TOKEN并添加到请求头
    client.DefaultRequestHeaders.Add("X-XSRF-TOKEN", GetXsrfTokenFromCookie());
    client.DefaultRequestHeaders.Add("Accept", "application/json");

    return client;
});

// 读取浏览器Cookie中XSRF-TOKEN的方法
string? GetXsrfTokenFromCookie()
{
    var cookies = Document.Cookie.Split(';');
    foreach (var cookie in cookies)
    {
        var parts = cookie.Split('=', StringSplitOptions.RemoveEmptyEntries);
        if (parts.Length == 2 && parts[0].Trim().Equals("XSRF-TOKEN", StringComparison.OrdinalIgnoreCase))
        {
            return parts[1].Trim();
        }
    }
    return null;
}
  1. 使用配置好的HttpClient发起POST请求:
// 调用CreateOrUpdateUserAsync示例
var updateModel = new UserUpdateModel();
await _httpClient.PostAsJsonAsync($"/api/users/{userId}", updateModel);

关键注意事项

  • HTTPS环境强制Secure属性:必须确保Cookie的Secure = true,否则浏览器会拒绝在HTTPS请求中携带Cookie。
  • 头名称完全一致:服务端配置的options.HeaderName必须和客户端添加的请求头名称完全匹配。
  • Cookie属性统一:.AspNetCore.Antiforgery.* Cookie与XSRF-TOKEN Cookie的SameSite、Secure属性需保持一致,避免被浏览器拦截。

内容的提问来源于stack exchange,提问作者Harry lyod

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:32:03