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
相关产品推荐
相关产品推荐

