Как сделать запрос ajax с токеном анти-подделки в mvc
У меня проблема с деталями ниже из проекта MVC.
Когда я пытаюсь использовать jquery-запрос ajax с панелью загрузки, например, spinning gif (или даже текст), я получаю ошибку, наблюдаемую у скрипача, который
Требуемое поле формы для защиты от подделки "__RequestVerificationToken" отсутствует.
Если я прокомментирую
[ValidateAntiForgeryToken] attribute
при методе действия POST и используйте панель загрузки, она работает нормально. Я хочу знать, почему я получаю эту ошибку.
Я даже использовал строку запроса, сериализованную с помощью
__RequestVerificationToken= $('input[name="__RequestVerificationToken"').val()
все еще я получаю ошибку
Запрет на подделку не может быть расшифрован. Если это приложение размещено веб-фермой или кластером, убедитесь, что на всех компьютерах установлена одна и та же версия веб-страниц ASP.NET, а в конфигурации <machineKey>
указаны явные ключи шифрования и проверки.
Автогенерация не может использоваться в кластере
Что я должен использовать?
Здесь он обновил код вопроса
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 action="/TransportJob/Create" method="post"><input name="__RequestVerificationToken" type="hidden" value="ydYSei0_RfyBf619dQrhDwwoCM7OwWkJQQEMNvNdAkefiFfYvRQ0MJYYu0zkktNxlJk_y1ZJO9-yb- COap8mqd0cvh8cDYYik4HJ0pZXTgE1" />
TransportJob
form tag 2 на той же странице
<form action="/TransportJobAddress/Create" method="post" novalidate="novalidate"><input name="__RequestVerificationToken" type="hidden" value="Np2vUZJPk1TJlv846oPSU6hg4SjMHRcCk1CacaqZbpHOg8WbV4GZv06noRDl7F_iT9qQf3BIXo3n9wGW68sU mki7g3-ku_BSHBDN-g2aaKc1">
Ответы
Ответ 1
Добавили ли вы токен в заголовок вызова ajax?
Вам нужно добавить AntiForgeryToken в свой заголовок сообщения в вызове ajax:
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('<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;
}
});
}
});
Добавлена строка заголовков в вашем вызове ajax.
Ответ 2
Вместо того, чтобы вручную добавлять его к каждому запросу, я обычно делаю что-то вроде этого:
var token = $('input[name="__RequestVerificationToken"]').val();
$.ajaxPrefilter(function (options, originalOptions) {
if (options.type.toUpperCase() == "POST") {
options.data = $.param($.extend(originalOptions.data, { __RequestVerificationToken: token }));
}
});
Это автоматически добавит ваш токен к любому POST-сообщению ajax.
Ответ 3
Добавили ли вы токен в свой вид? Вот так:
<form method="post" action="/my-controller/my-action">
@Html.AntiForgeryToken()
</form>
Поскольку ваш контроллер, получающий сообщение, ищет токен анти-подделки, вам нужно убедиться, что вы добавили его в свою форму в виде.
EDIT:
Сначала создайте свои данные в json:
var formData = $('form[action="/TransportJobAddress/Create"]').serialize();
$.extend(formData, {'__RequestVerificationToken': token });
//and then in your ajax call:
$.ajax({
//...
data:formData
//...
});
Ответ 4
Вид или макет:
< form id = '_ id' method = 'POST' > @html.antiforgeryToken(); </Формa >
Функция вызова ajax:
var data={...};
var token=$('#_id').serializeObject();
var dataWithAntiforgeryToken = $.extend(data,token);
$.ajax(
{
....,
data: dataWithAntiforgeryToken;
}
)
Ответ 5
Я хотел защитить оба Ajax и обычный запрос, поэтому вот что я получил:
Сначала используйте отличный блог из haacked.com я Создал ConditionalFilterProvider, как описано.
Затем я создал все классы, как описано в блоге, из codethinked.
На моей странице _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().
Чтобы доказать, что все сработало, я просто пытаюсь записать вещи с помощью формы без AntiForgeryToken и получить ожидаемое исключение.
И удалите $.ajaxPrefilter и создайте Ajax-запросы, и ожидаемое исключение было получено.