ASP.NET Core 7 + React 项目Antiforgery Token失效问题求助
ASP.NET Core 7 + React 实现Antiforgery防护的问题修复
现有代码的核心问题
- Program.cs中
AddAntiforgery存在语法错误,且属性名使用错误 - 未提供生成反伪造令牌的GET端点,React请求的
GET /Test2不存在(Test2仅定义了Post方法) - React端获取令牌的逻辑错误:令牌存储在Cookie中而非响应JSON,且请求头直接传入函数而非实际令牌值
- 跨域场景下未配置CORS允许携带Cookie和自定义请求头
修复步骤
1. 修正Program.cs的Antiforgery及CORS配置
// 配置Antiforgery builder.Services.AddAntiforgery(options => { options.Cookie.Name = "X-XSRF-TOKEN"; options.HeaderName = "X-XSRF-TOKEN"; // 注意正确属性名是HeaderName,不是Header options.Cookie.SameSite = SameSiteMode.Lax; // 跨域场景建议设为Lax或None(None需配合Secure) options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // HTTPS环境下启用 }); // 配置CORS(跨域场景必填) builder.Services.AddCors(options => { options.AddPolicy("AllowReact", policy => { policy.WithOrigins("http://localhost:3000") // 替换为你的React项目地址 .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); // 允许携带Cookie }); }); var app = builder.Build(); // 启用CORS(需放在UseRouting之后,UseAuthorization之前) app.UseCors("AllowReact"); app.UseAuthorization(); app.MapControllers(); app.Run();
2. 添加生成反伪造令牌的GET端点
在Controller中新增一个专门的GET接口,用于触发令牌写入Cookie:
[Route("/api/csrf-token")] [HttpGet] [IgnoreAntiforgeryToken] // 该端点无需验证,仅用于生成令牌 public IActionResult GetCsrfToken() { var antiforgery = HttpContext.RequestServices.GetRequiredService<IAntiforgery>(); antiforgery.GetAndStoreTokens(HttpContext); // 将令牌写入Cookie return Ok(); }
3. 修正React端的令牌获取与请求逻辑
// 从Cookie中提取XSRF令牌的工具函数 const getCsrfTokenFromCookie = () => { const cookies = document.cookie.split('; '); const csrfCookie = cookies.find(c => c.startsWith('X-XSRF-TOKEN=')); return csrfCookie ? decodeURIComponent(csrfCookie.split('=')[1]) : ''; }; // 初始化时触发令牌生成(写入Cookie) useEffect(() => { fetch("https://localhost:7277/api/csrf-token", { method: "GET", credentials: "include" // 必须添加,否则Cookie不会被浏览器保存 }); }, []); const handleSubmit = async (e) => { e.preventDefault(); const csrfToken = getCsrfTokenFromCookie(); try { const res = await fetch("https://localhost:7277/Test2", { method: "POST", headers: { "Content-Type": "application/json", "X-XSRF-TOKEN": csrfToken }, credentials: "include", // 携带Cookie body: JSON.stringify({ "vehicleReg": inputValue.current.value }) }); if (!res.ok) { throw new Error(`请求失败:${res.status}`); } const data = await res.json(); console.log("发送成功", data); } catch (er) { console.log("请求出错", er); } };
4. 全局配置Antiforgery验证(可选)
如果希望所有POST/PUT/DELETE请求自动验证令牌,可在Program.cs中全局配置,无需每个Controller方法添加[ValidateAntiForgeryToken]:
builder.Services.AddControllers(options => { options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); });
关键注意事项
- 跨域场景下,CORS的
AllowCredentials必须开启,同时React的fetch请求要添加credentials: "include" - Antiforgery Cookie的
SameSite和Secure属性需根据部署环境调整(本地HTTP可设SameSiteMode.Lax、CookieSecurePolicy.None) - 令牌由ASP.NET Core写入Cookie,前端只需从Cookie提取后放入请求头即可
内容的提问来源于stack exchange,提问作者user2038084
相关产品推荐
相关产品推荐

