如何在mvc中使用防伪令牌发出ajax请求

我对MVC项目的以下细节有疑问。

当我试图使用jquery ajax请求加载面板像旋转gif(甚至文本)时,我收到错误,从提琴手观察到

所需的防伪表单字段“__RequestVerificationToken”不存在。

如果我在POST操作方法中注释[ValidateAntiForgeryToken] attribute并使用加载面板它工作正常。我想知道为什么我收到此错误。

我甚至使用了序列化的查询字符串

 __RequestVerificationToken= $('input[name="__RequestVerificationToken"').val() 

我仍然得到错误

防伪令牌无法解密。 如果此应用程序由Web场或群集托管,请确保所有计算机都运行相同版本的ASP.NET网页,并且配置指定显式​​加密和validation密钥。

AutoGenerate不能在群集中使用

我该怎么用?

这里更新了问题代码

 var token = $('input[name="__RequestVerificationToken"]').val(); $('#submitaddress').click(function subaddr(event) { event.preventDefault(); event.stopPropagation(); //$('#addAddress').html(' Sending...'); // $('#addAddress').blur(); // $(this).bl if ($('#Jobid').val()!="") { $('#TransportJobId').val(parseInt($('#Jobid').val())); $.ajax( { url: '/TransportJobAddress/create', type: 'POST', data: "__RequestVerificationToken=" + token + "" + $('form[action="/TransportJobAddress/Create"]').serialize(), success: function poste(data, textStatus, jqXHR) { $('#addAddress').html(data); return false; }, error: function err(jqXHR, textStatus, errorThrown) { alert('error at address :' + errorThrown); } }); } else { var transportid = 2; $.ajax({ url: '/TransportJob/create', type: 'POST', data: "__RequestVerificationToken=" + token + "" + $('form[action="/TransportJob/Create"]').serialize(), success: function sfn(data, textStatus, jqXHR) { transportid = parseInt(data); $('#Jobid').val(data); // alert('inserted id :' + data); $('#TransportJobId').val((transportid)); $.ajax( { url: '/TransportJobAddress/create', type: 'POST', //beforeSend: function myintserver(xhr){ // $('#addAddress').html('
please wait ...
'); //}, data: "__RequestVerificationToken=" + token + "" + $('form[action="/TransportJobAddress/Create"]').serialize(), success: function poste(data, textStatus, jqXHR) { $('#addAddress').html(data); }, error: function err(jqXHR, textStatus, errorThrown) { alert('error at address :' + errorThrown); } }); }, error: function myfunction(jqXHR, textStatus, errorThrown) { alert("error at transport :" + jqXHR.textStatus); }, complete: function completefunc() { // alert('ajax completed all requests'); return false; } }); } });

表格标签

 

TransportJob表单标记2在同一页面上

  

您是否已将令牌添加到ajax调用的标头中?

您需要在ajax调用的消息头中添加AntiForgeryToken:

 var token = $('input[name="__RequestVerificationToken"]').val(); var headers = {}; headers['__RequestVerificationToken'] = token; $.ajax({ url: ... some url, headers: headers, .... }); 

在你的代码中尝试这个:

 var token = $('input[name="__RequestVerificationToken"]').val(); var tokenadr = $('form[action="/TransportJobAddress/Create"] input[name="__RequestVerificationToken"]').val(); var headers = {}; var headersadr = {}; headers['__RequestVerificationToken'] = token; headersadr['__RequestVerificationToken'] = tokenadr; $('#submitaddress').click(function subaddr(event) { event.preventDefault(); event.stopPropagation(); //$('#addAddress').html(' Sending...'); // $('#addAddress').blur(); // $(this).bl if ($('#Jobid').val()!="") { $('#TransportJobId').val(parseInt($('#Jobid').val())); $.ajax( { url: '/TransportJobAddress/create', type: 'POST', headers:headersadr, data: "__RequestVerificationToken=" + token + "" + $('form[action="/TransportJobAddress/Create"]').serialize(), success: function poste(data, textStatus, jqXHR) { $('#addAddress').html(data); return false; }, error: function err(jqXHR, textStatus, errorThrown) { alert('error at address :' + errorThrown); } }); } else { var transportid = 2; $.ajax({ url: '/TransportJob/create', type: 'POST', headers:headers, data: $('form[action="/TransportJob/Create"]').serialize(), success: function sfn(data, textStatus, jqXHR) { transportid = parseInt(data); $('#Jobid').val(data); // alert('inserted id :' + data); $('#TransportJobId').val((transportid)); $.ajax( { url: '/TransportJobAddress/create', type: 'POST', //beforeSend: function myintserver(xhr){ // $('#addAddress').html('
please wait ...
'); //}, headers:headers, data: $('form[action="/TransportJobAddress/Create"]').serialize(), success: function poste(data, textStatus, jqXHR) { $('#addAddress').html(data); }, error: function err(jqXHR, textStatus, errorThrown) { alert('error at address :' + errorThrown); } }); }, error: function myfunction(jqXHR, textStatus, errorThrown) { alert("error at transport :" + jqXHR.textStatus); }, complete: function completefunc() { // alert('ajax completed all requests'); return false; } }); } });

在ajax调用中添加了标题行。

我不是手动将其添加到每个请求中,而是通常执行以下操作:

 var token = $('input[name="__RequestVerificationToken"]').val(); $.ajaxPrefilter(function (options, originalOptions) { if (options.type.toUpperCase() == "POST") { options.data = $.param($.extend(originalOptions.data, { __RequestVerificationToken: token })); } }); 

这会自动将您的令牌添加到您执行的任何 ajax POST。

您是否已将令牌添加到View中? 像这样:

  @Html.AntiForgeryToken()  

由于接收post的控制器正在寻找防伪令牌,因此您需要确保将其添加到视图中的表单中。

编辑:

首先尝试在json中构建数据:

 var formData = $('form[action="/TransportJobAddress/Create"]').serialize(); $.extend(formData, {'__RequestVerificationToken': token }); //and then in your ajax call: $.ajax({ //... data:formData //... }); 

查看或布局:

@ html.antiforgeryToken();

ajax调用函数

 var data={...}; var token=$('#_id').serializeObject(); var dataWithAntiforgeryToken = $.extend(data,token); $.ajax( { ...., data: dataWithAntiforgeryToken; } ) 

我想保护Ajax和普通请求,所以这就是我提出的:

首先使用haacked.com的优秀博客我按照描述创建了ConditionalFilterProvider。

然后我创建了代码插入博客中描述的所有类。

在我的_layout页面上,我添加了篇幅为$ .ajaxPrefilter,如博客中所述…这确保我所有的Ajax回调现在都通过标题发送Antiforgery令牌。

为了将所有内容粘合在一起,我在global.asax / Application_Start上添加了这段代码

 (c, a) => (c.HttpContext.Request.IsAjaxRequest() && !string.Equals(c.HttpContext.Request.HttpMethod, "GET")) ? new AjaxValidateAntiForgeryTokenAttribute() : null, (c, a) => (!c.HttpContext.Request.IsAjaxRequest() && string.Equals(c.HttpContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase)) ? new ValidateAntiForgeryTokenAttribute() : null 

基本上..将属性注入我不是GET的所有控制器。

之后,我只需要访问所有(极少数)表单并添加@ Html.AntiForgeryToken()。

为了certificate一切正常,我只是尝试使用没有AntiForgeryToken的表单来确定事物,并获得预期的exception。 并删除$ .ajaxPrefilter并创建Ajax请求并收到预期的exception。