ASP.NET Core WebAPI防伪令牌验证失败问题排查求助
解决ASP.NET Core 2 WebAPI与Angular 5防伪令牌交换错误的问题
你遇到的"Validation of the provided antiforgery token failed. The cookie token and the request token were swapped"错误,核心原因是ASP.NET Core Antiforgery的令牌结构和Angular的默认防伪机制不匹配,导致客户端发送的令牌和服务器期望的位置搞反了。下面一步步帮你排查和解决:
1. 先理清两者的默认行为差异
- Angular 5默认逻辑:自动读取名为
XSRF-TOKEN的Cookie值,然后将其放到请求头X-XSRF-TOKEN中,随POST/PUT/DELETE请求发送。 - ASP.NET Core Antiforgery默认逻辑:生成两个关联的令牌:
- 一个存储在Cookie中的Cookie令牌(默认名称
__RequestVerificationToken) - 一个需要随请求发送的请求令牌(可以是表单字段或请求头)
服务器验证时,需要同时收到这两个令牌,且它们必须匹配。
- 一个存储在Cookie中的Cookie令牌(默认名称
你的配置错误在于直接将Antiforgery的Cookie名称设为XSRF-TOKEN,导致Angular把Cookie令牌当成请求令牌发送,服务器自然会判定两者交换了。
2. 修正Startup.cs的Antiforgery配置
首先修改ConfigureServices中的Antiforgery配置,调整为适配Angular的逻辑:
public void ConfigureServices(IServiceCollection services) { // ...其他配置 services.AddAntiforgery(options => { // 保持Antiforgery的Cookie为默认名称(或自定义内部名称,不要用XSRF-TOKEN) // options.Cookie.Name = "__RequestVerificationToken"; // 可省略,默认值就是这个 options.HeaderName = "X-XSRF-TOKEN"; // 告诉服务器从这个头读取请求令牌 options.FormFieldName = "F-XSRF-TOKEN"; // 修正拼写错误(你之前写的是XSFR) }); // ...其他配置 }
3. 添加中间件生成并设置XSRF-TOKEN Cookie
接下来需要在请求管道中添加一个中间件,负责生成Antiforgery的请求令牌,并将其写入XSRF-TOKEN Cookie,供Angular读取:
在Configure方法中,在app.UseMvc()之前添加:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAntiforgery antiforgery) { // ...其他中间件(比如UseStaticFiles、UseAuthentication等) // 添加生成XSRF-TOKEN的中间件 app.Use(async (context, next) => { // 针对GET/HEAD/OPTIONS请求,生成并设置XSRF-TOKEN Cookie if (context.Request.Method == "GET" || context.Request.Method == "HEAD" || context.Request.Method == "OPTIONS") { // 获取请求令牌 var tokens = antiforgery.GetAndStoreTokens(context); // 将请求令牌写入XSRF-TOKEN Cookie,设置SameSite和禁用HttpOnly(否则Angular无法读取) context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false, SameSite = SameSiteMode.Strict }); } await next(); }); app.UseMvc(); }
这里的关键细节:
- 只对安全的GET类请求生成令牌(避免重复生成)
HttpOnly = false:必须禁用HttpOnly,否则Angular的JavaScript无法读取这个CookieSameSite = SameSiteMode.Strict:提升安全性,防止跨站请求
4. 给需要验证的API方法添加防伪验证
在你的POST/PUT/DELETE控制器方法上添加[ValidateAntiForgeryToken]特性:
[HttpPost] [ValidateAntiForgeryToken] public IActionResult Create([FromBody] YourModel model) { // ...你的业务逻辑 }
如果想让所有API都验证,可以在控制器上添加这个特性,或者配置全局过滤器。
5. 跨域场景额外配置(如果需要)
如果你的Angular应用和WebAPI不在同一域名下,需要在ASP.NET Core中配置CORS允许凭据:
services.AddCors(options => { options.AddPolicy("AllowAngularApp", builder => builder.WithOrigins("http://your-angular-domain.com") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials()); });
然后在Configure中启用CORS:
app.UseCors("AllowAngularApp");
常见坑点排查
- 拼写错误:你之前的
FormFieldName写成了F-XSFR-TOKEN,正确应该是F-XSRF-TOKEN(虽然Angular用不到表单字段,但还是建议修正) HttpOnly设置:如果XSRF-TOKENCookie的HttpOnly设为true,Angular无法读取,导致请求头没有令牌- 跨域时未启用
AllowCredentials:CORS必须允许携带Cookie,否则Angular不会发送X-XSRF-TOKEN头
按照以上步骤配置后,应该就能解决令牌交换的错误了。
内容的提问来源于stack exchange,提问作者NCC-2909-M
相关产品推荐
相关产品推荐

