.NET 6 API Post请求为何不接受Anti-Forgery Token?
我使用Vue3响应式框架,通过API提交表单到.NET6后端,但请求的防伪令牌(Anti-Forgery Token)不被接受。模仿传统表单提交方式将令牌放在请求体中,JS代码如下:
var token = $('input[name="__RequestVerificationToken"]').val(); var url = '/api/ShareAllocations'; $.ajax({ type: "POST", url: url, data: { fa: fa, '__RequestVerificationToken': token }, success: function (result) { console.log(result) }, complete: function (e) { }, error: function (xhr, ajaxOptions, thrownError) { alert(xhr.responseText); } });
Fiddler捕获的请求体文本视图:
Fa= … (Json数据)
__RequestVerificationToken=CfDJ8BSiPpdXlmRFvbl4LFJ0x7iHfmWBSdPblTwBjlLUq-We2oD60dKqBCYx4dUwXG5Gxprtl3lW2zzs4K8_iBf8eu0RQqOM928ANv1-16rcqizvYhUDFC5iaDo97wpqCsdFFxlmhiRaHW1zxhmEcwpYMrpZWBnzUbjGkTa-qUSs5GfuT2MwJGEWWYqyz7D95RRJVA
API调用返回200,但网页显示400错误请求。Fiddler记录:
143 200 HTTPS localhost:7164 /api/ShareAllocations
144 400 HTTPS localhost:7164 /FarmAllocation/Manage
对比.NET Core传统表单提交的请求体,防伪令牌的键值对格式一致:
SENIOR_LIVING_FACILITIES.FACILITY_ID=0&SENIOR_LIVING_FACILITIES.FACILITY_NAME=n&SENIOR_LIVING_FACILITIES.ADDRESS=&SENIOR_LIVING_FACILITIES.CITY=&SENIOR_LIVING_FACILITIES.STATE=ME&SENIOR_LIVING_FACILITIES.ZIP=&SENIOR_LIVING_FACILITIES.CONTACT_NAME=&SENIOR_LIVING_FACILITIES.CONTACT_ROLE=&SENIOR_LIVING_FACILITIES.PHONE=&SENIOR_LIVING_FACILITIES.EMAIL=&__RequestVerificationToken=CfDJ8BSiPpdXlmRFvbl4LFJ0x7iHfmWBSdPblTwBjlLUq-We2oD60dKqBCYx4dUwXG5Gxprtl3lW2zzs4K8_iBf8eu0RQqOM928ANv1-16rcqizvYhUDFC5iaDo97wpqCsdFFxlmhiRaHW1zxhmEcwpYMrpZWBnzUbjGkTa-qUSs5GfuT2MwJGEWWYqyz7D95RRJVA
问题分析与解决方案
1. 核心异常点排查
API返回200但页面跳转后出现400,说明异常并非来自API请求本身,而是后续/FarmAllocation/Manage页面的请求存在问题:
- 若该页面是GET请求却触发400,需检查后端是否为GET请求强制开启了防伪验证(默认.NET6不验证GET请求);
- 若为POST跳转,需确认跳转时是否携带了有效防伪令牌。
2. 规范API请求格式
当前请求混合了表单字段与JSON数据,可能导致后端解析异常,可通过两种方式修正:
方式一:纯表单编码提交
将fa对象序列化为表单格式,和令牌一起提交:
var token = $('input[name="__RequestVerificationToken"]').val(); var url = '/api/ShareAllocations'; // 序列化fa对象并拼接令牌 var formData = $.param(fa) + '&__RequestVerificationToken=' + encodeURIComponent(token); $.ajax({ type: "POST", url: url, data: formData, contentType: 'application/x-www-form-urlencoded; charset=UTF-8', success: function (result) { console.log(result) }, error: function (xhr, ajaxOptions, thrownError) { alert(xhr.responseText); } });
方式二:JSON格式提交(推荐)
将令牌放在请求头中传递,同时后端需配置支持从header读取令牌:
var token = $('input[name="__RequestVerificationToken"]').val(); var url = '/api/ShareAllocations'; $.ajax({ type: "POST", url: url, data: JSON.stringify({ fa: fa }), contentType: 'application/json; charset=UTF-8', headers: { 'RequestVerificationToken': token }, success: function (result) { console.log(result) }, error: function (xhr, ajaxOptions, thrownError) { alert(xhr.responseText); } });
3. 后端配置确认
确保后端已正确配置防伪验证:
- 在
Program.cs中添加配置:
builder.Services.AddAntiforgery(options => { options.HeaderName = "RequestVerificationToken"; // 对应前端请求头的令牌键名 });
- 在API的Action或控制器上添加
[ValidateAntiForgeryToken]特性。
4. 防伪Cookie检查
验证AJAX请求是否携带了.AspNetCore.Antiforgery.*开头的Cookie:
- Fiddler中查看请求的Cookie头,确认该Cookie存在;
- 若缺失,需确保页面通过
@Html.AntiForgeryToken()生成令牌时,已自动设置对应Cookie。
内容的提问来源于stack exchange,提问作者Roland Wales

