[英]How to make ajax request with anti-forgery token in mvc
I have problem with below details from MVC project. 我对MVC项目的以下细节有疑问。
When I am trying to use jquery ajax request with loading panel like spinning gif (or even text), I am getting error, observed from fiddler that 当我试图使用jquery ajax请求加载面板像旋转gif(甚至文本)时,我收到错误,从提琴手观察到
The required anti-forgery form field "__RequestVerificationToken" is not present. 所需的防伪表单字段“__RequestVerificationToken”不存在。
If I comment [ValidateAntiForgeryToken] attribute
at POST action method and use loading panel it is working fine.I want to know why I am getting this error. 如果我在POST操作方法中注释[ValidateAntiForgeryToken] attribute
并使用加载面板它工作正常。我想知道为什么我收到此错误。
I have even used the query string serialized with 我甚至使用了序列化的查询字符串
__RequestVerificationToken= $('input[name="__RequestVerificationToken"').val()
still I am getting error 我仍然得到错误
The anti-forgery token could not be decrypted. 防伪令牌无法解密。 If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the
<machineKey>
configuration specifies explicit encryption and validation keys. 如果此应用程序由Web场或群集托管,请确保所有计算机都运行相同版本的ASP.NET网页,并且<machineKey>
配置指定显式加密和验证密钥。
AutoGenerate cannot be used in a cluster AutoGenerate不能在群集中使用
What should I use? 我该怎么用?
Here it updated question code 这里更新了问题代码
var token = $('input[name="__RequestVerificationToken"]').val();
$('#submitaddress').click(function subaddr(event) {
event.preventDefault();
event.stopPropagation();
//$('#addAddress').html('<img src="/img/animated-overlay.gif"> 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('<div id="temp_load" style="text-align:center">please wait ...</div>');
//},
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;
}
});
}
});
form tags 表格标签
<form action="/TransportJob/Create" method="post"><input name="__RequestVerificationToken" type="hidden" value="ydYSei0_RfyBf619dQrhDwwoCM7OwWkJQQEMNvNdAkefiFfYvRQ0MJYYu0zkktNxlJk_y1ZJO9-yb- COap8mqd0cvh8cDYYik4HJ0pZXTgE1" />
TransportJob form tag 2 on same page TransportJob表单标记2在同一页面上
<form action="/TransportJobAddress/Create" method="post" novalidate="novalidate"><input name="__RequestVerificationToken" type="hidden" value="Np2vUZJPk1TJlv846oPSU6hg4SjMHRcCk1CacaqZbpHOg8WbV4GZv06noRDl7F_iT9qQf3BIXo3n9wGW68sU mki7g3-ku_BSHBDN-g2aaKc1">
Rather than manually adding it to each request, I usually do something like this: 我不是手动将其添加到每个请求中,而是通常执行以下操作:
var token = $('input[name="__RequestVerificationToken"]').val();
$.ajaxPrefilter(function (options, originalOptions) {
if (options.type.toUpperCase() == "POST") {
options.data = $.param($.extend(originalOptions.data, { __RequestVerificationToken: token }));
}
});
This will automatically add your token to any ajax POST you do. 这会自动将您的令牌添加到您执行的任何 ajax POST。
Have you added your token to the header of the ajax call? 您是否已将令牌添加到ajax调用的标头中?
You need to add AntiForgeryToken in your message header in the ajax call: 您需要在ajax调用的消息头中添加AntiForgeryToken:
var token = $('input[name="__RequestVerificationToken"]').val();
var headers = {};
headers['__RequestVerificationToken'] = token;
$.ajax({
url: ... some url,
headers: headers,
....
});
Try this in your code: 在您的代码中尝试此操作:
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('<img src="/img/animated-overlay.gif"> 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('<div id="temp_load" style="text-align:center">please wait ...</div>');
//},
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;
}
});
}
});
Added headers line in your ajax call. 在ajax调用中添加了标题行。
Have you added the token to your View? 您是否已将令牌添加到View中? Like this: 像这样:
<form method="post" action="/my-controller/my-action">
@Html.AntiForgeryToken()
</form>
Since your controller receiving the post is looking for the anti forgery token, you need to ensure that you add it to your form in the view. 由于接收帖子的控制器正在寻找防伪令牌,因此您需要确保将其添加到视图中的表单中。
EDIT: 编辑:
Try building your data in json first: 首先尝试在json中构建数据:
var formData = $('form[action="/TransportJobAddress/Create"]').serialize();
$.extend(formData, {'__RequestVerificationToken': token });
//and then in your ajax call:
$.ajax({
//...
data:formData
//...
});
View or Layout: 查看或布局:
< form id='_id' method='POST'> @html.antiforgeryToken(); <form id ='_ id'methode ='POST'> @ html.antiforgeryToken(); < /form> </ form>
The ajax call function : ajax调用函数 :
var data={...};
var token=$('#_id').serializeObject();
var dataWithAntiforgeryToken = $.extend(data,token);
$.ajax(
{
....,
data: dataWithAntiforgeryToken;
}
)
I wanted to secure both Ajax and normal request, so here is what I came out with: 我想保护Ajax和普通请求,所以这就是我提出的:
First using the excellent blog from haacked.com I Created the ConditionalFilterProvider as described. 首先使用来自haacked.com的优秀博客我按照描述创建了ConditionalFilterProvider。
Then I created all the classes as described on the blog from codethinked . 然后我创建了所有类,如博客中所描述的codethinked 。
On my _layout page I added the piece with the $.ajaxPrefilter as described in the blog... This assures that all my Ajax-callback now send the Antiforgery token through header. 在我的_layout页面上,我添加了一个带有$ .ajaxPrefilter的文章,如博客中所述...这确保我所有的Ajax回调现在都通过标题发送Antiforgery令牌。
To glue all together I added this piece of code on my global.asax / Application_Start 为了将所有内容粘合在一起,我在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
Basically.. inject the attribute to all my Controllers that are not GET. 基本上..将属性注入我不是GET的所有控制器。
After that I just had to go to all my (Very few) forms and add the @Html.AntiForgeryToken(). 之后,我只需要访问所有(极少数)表单并添加@ Html.AntiForgeryToken()。
To proof that all worked I just try to dens things with a form without the AntiForgeryToken and get the expected exception. 为了证明一切正常,我只是尝试使用没有AntiForgeryToken的表单来确定事物,并获得预期的异常。 And remove the $.ajaxPrefilter and create Ajax requests and the expected exception was received. 并删除$ .ajaxPrefilter并创建Ajax请求并收到预期的异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.