.NET Core Antiforgery Token双Cookie导致验证失败的问题咨询
双Antiforgery Token导致验证失败的问题定位与修复
问题根因
- 中间件触发逻辑过于粗放:原逻辑只要请求路径包含
api就直接调用GetAndStoreTokens方法。当页面首次加载时并行发起多个API GET请求时,每个请求都会独立生成一套绑定当前请求的防伪令牌,反复覆盖XSRF-TOKENCookie的值,最终导致前端读取到的令牌和后端实际用于校验的令牌不匹配。 - Cookie作用域未做统一约束:自定义写入的
XSRF-TOKENCookie没有显式设置Path属性,默认会继承当前请求的路径作为作用域。当分别在根路径、/api子路径下生成同名称Cookie时,会形成两个独立的存储值,进一步放大令牌不匹配的问题。 - 令牌生成逻辑的固有特性被忽略:
GetAndStoreTokens方法会同步生成HttpOnly的防伪认证Cookie,该Cookie和返回的请求令牌是一一绑定的。反复调用该方法会持续替换绑定关系,即便前端能正常读到请求令牌,也会因为认证Cookie和请求令牌的绑定关系错位导致校验失败。
修复方案
1. 补全Antiforgery全局配置
在ConfigureServices方法中统一防伪认证Cookie的基础配置,和后续自定义的前端可读Cookie保持一致的作用域规则:
services.AddAntiforgery(options => { options.HeaderName = "X-CSRF-TOKEN"; options.Cookie.HttpOnly = true; options.Cookie.SameSite = SameSiteMode.Lax; options.Cookie.Path = "/"; options.Cookie.IsEssential = true; });
2. 重构中间件的令牌写入逻辑
替换原有路径匹配的粗粒度逻辑,仅对安全类请求做令牌初始化,同时增加前置判断避免重复生成令牌覆盖Cookie:
app.Use(async (context, next) => { // 仅处理GET/HEAD这类安全请求,POST/PUT/DELETE等带副作用的请求直接走防伪校验逻辑 if (HttpMethods.IsGet(context.Request.Method) || HttpMethods.IsHead(context.Request.Method)) { // 检查是否已经完成过防伪令牌初始化,避免重复生成 var antiforgeryFeature = context.Features.Get<IAntiforgeryFeature>(); if (antiforgeryFeature?.IsAfterGetCookie == false) { var tokens = antiforgery.GetAndStoreTokens(context); context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false, SameSite = SameSiteMode.Lax, Path = "/", IsEssential = true }); } } await next(); });
3. 配套排查项
- 清理浏览器中残留的多路径作用域
XSRF-TOKENCookie,配置生效后确认全站仅存在一个根路径作用域的同名称Cookie - 调整中间件注册顺序:将上述防伪写入逻辑放在
UseRouting()之后、所有API业务处理逻辑之前,避免响应流已经开始输出后再尝试写Cookie导致配置不生效 - HTTPS部署环境下,为两类防伪Cookie补充
Secure = true配置,避免混合内容场景下Cookie丢失触发的重复生成 - 禁止在控制器过滤器、接口业务逻辑中重复调用
GetAndStoreTokens方法,避免每次请求都覆盖Cookie值
内容的提问来源于stack exchange,提问作者Pradeep Prabhu
相关产品推荐
相关产品推荐

