У меня возникают проблемы с AntiForgeryToken с помощью ajax. Я использую ASP.NET MVC 3. Я попробовал решение в jQuery Ajax-вызовах и Html.AntiForgeryToken(). Используя это решение, токен теперь передается:
var data = { ... } // with token, key is '__RequestVerificationToken'
$.ajax({
type: "POST",
data: data,
datatype: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
url: myURL,
success: function (response) {
...
},
error: function (response) {
...
}
});
Когда я удаляю атрибут [ValidateAntiForgeryToken]
, чтобы увидеть, передаются ли данные (с маркером) в качестве параметров для контроллера, я вижу, что они передаются. Но по какой-то причине сообщение A required anti-forgery token was not supplied or was invalid.
все еще появляется, когда я возвращаю атрибут.
Любые идеи?
ИЗМЕНИТЬ
Внутри формы генерируется antiforgerytoken, но я не использую действие отправки, чтобы отправить его. Вместо этого, я просто получаю значение токена, используя jquery, а затем пытаюсь выполнить ajax post.
Вот форма, содержащая токен, и расположена на главной главной странице:
<form id="__AjaxAntiForgeryForm" action="#" method="post">
@Html.AntiForgeryToken()
</form>
Вы неправильно указали contentType
на application/json
.
Вот пример того, как это может работать.
Контроллер:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(string someValue)
{
return Json(new { someValue = someValue });
}
}
Вид:
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
@Html.AntiForgeryToken()
}
<div id="myDiv" data-url="@Url.Action("Index", "Home")">
Click me to send an AJAX request to a controller action
decorated with the [ValidateAntiForgeryToken] attribute
</div>
<script type="text/javascript">
$('#myDiv').submit(function () {
var form = $('#__AjaxAntiForgeryForm');
var token = $('input[name="__RequestVerificationToken"]', form).val();
$.ajax({
url: $(this).data('url'),
type: 'POST',
data: {
__RequestVerificationToken: token,
someValue: 'some value'
},
success: function (result) {
alert(result.someValue);
}
});
return false;
});
</script>
Другой (менее javascriptish) подход, который я сделал, выглядит примерно так:
public static MvcHtmlString AntiForgeryTokenForAjaxPost(this HtmlHelper helper)
{
var antiForgeryInputTag = helper.AntiForgeryToken().ToString();
// Above gets the following: <input name="__RequestVerificationToken" type="hidden" value="PnQE7R0MIBBAzC7SqtVvwrJpGbRvPgzWHo5dSyoSaZoabRjf9pCyzjujYBU_qKDJmwIOiPRDwBV1TNVdXFVgzAvN9_l2yt9-nf4Owif0qIDz7WRAmydVPIm6_pmJAI--wvvFQO7g0VvoFArFtAR2v6Ch1wmXCZ89v0-lNOGZLZc1" />
var removedStart = antiForgeryInputTag.Replace(@"<input name=""__RequestVerificationToken"" type=""hidden"" value=""", "");
var tokenValue = removedStart.Replace(@""" />", "");
if (antiForgeryInputTag == removedStart || removedStart == tokenValue)
throw new InvalidOperationException("Oops! The Html.AntiForgeryToken() method seems to return something I did not expect.");
return new MvcHtmlString(string.Format(@"{0}:""{1}""", "__RequestVerificationToken", tokenValue));
}
__RequestVerificationToken:"P5g2D8vRyE3aBn7qQKfVVVAsQc853s-naENvpUAPZLipuw0pa_ffBf9cINzFgIRPwsf7Ykjt46ttJy5ox5r3mzpqvmgNYdnKc1125jphQV0NnM5nGFtcXXqoY3RpusTH_WcHPzH4S4l1PmB8Uu7ubZBftqFdxCLC5n-xT0fHcAY1"
$(function () {
$("#submit-list").click(function () {
$.ajax({
url: '@Url.Action("SortDataSourceLibraries")',
data: { items: $(".sortable").sortable('toArray'), @Html.AntiForgeryTokenForAjaxPost() },
type: 'post',
traditional: true
});
});
});
И это работает!
@Html.AntiForgeryTokenForAjaxPost
на две части, чтобы получить имя токена в одной руке и его значение в другой. Иначе подсветка синтаксиса все испортила. Это заканчивается так (убрал одинарные кавычки из возвращаемого результата, так что он ведет себя как любой помощник MVC, например, @Url): '@Html.AntiForgeryTokenName' : '@Html.AntiForgeryTokenValue'
Это так просто! когда вы используете @Html.AntiForgeryToken()
в своем html-коде, это означает, что сервер подписал эту страницу, и каждый запрос, отправленный на сервер с этой конкретной страницы, имеет знак, которому запрещено отправлять фальшивый запрос хакерами. поэтому для аутентификации этой страницы сервером вы должны пройти два этапа:
1.send параметр с именем __RequestVerificationToken
и для получения его значений используйте коды ниже:
<script type="text/javascript">
function gettoken() {
var token = '@Html.AntiForgeryToken()';
token = $(token).val();
return token;
}
</script>
например, выполните вызов ajax
$.ajax({
type: "POST",
url: "/Account/Login",
data: {
__RequestVerificationToken: gettoken(),
uname: uname,
pass: pass
},
dataType: 'json',
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
success: successFu,
});
и шаг 2 просто украсить ваш метод действий [ValidateAntiForgeryToken]
function DeletePersonel(id) { var data = new FormData(); data.append("__RequestVerificationToken", "@HtmlHelper.GetAntiForgeryToken()"); $.ajax({ type: 'POST', url: '/Personel/Delete/' + id, data: data, cache: false, processData: false, contentType: false, success: function (result) { } }); } public static class HtmlHelper { public static string GetAntiForgeryToken() { System.Text.RegularExpressions.Match value = System.Text.RegularExpressions.Regex.Match(System.Web.Helpers.AntiForgery.GetHtml().ToString(), "(?:value=\")(.*)(?:\")"); if (value.Success) { return value.Groups[1].Value; } return ""; } }
Я знаю, что это старый вопрос. Но я все равно добавлю свой ответ, может помочь кому-то вроде меня.
Если вы не хотите обрабатывать результат после действия контроллера, например вызов метода LoggOff
контроллера Accounts
, вы можете сделать следующую версию ответа @DarinDimitrov:
@using (Html.BeginForm("LoggOff", "Accounts", FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
@Html.AntiForgeryToken()
}
<!-- this could be a button -->
<a href="#" id="ajaxSubmit">Submit</a>
<script type="text/javascript">
$('#ajaxSubmit').click(function () {
$('#__AjaxAntiForgeryForm').submit();
return false;
});
</script>
В Asp.Net MVC при использовании @Html.AntiForgeryToken()
Razor создает скрытое поле ввода с именем __RequestVerificationToken
для хранения токенов. Если вы хотите написать реализацию AJAX, вы должны сами получить этот токен и передать его в качестве параметра на сервер, чтобы его можно было проверить.
Шаг 1: Получить маркер
var token = $('input[name="`__RequestVerificationToken`"]').val();
Шаг 2: Передайте токен в вызове AJAX
function registerStudent() {
var student = {
"FirstName": $('#fName').val(),
"LastName": $('#lName').val(),
"Email": $('#email').val(),
"Phone": $('#phone').val(),
};
$.ajax({
url: '/Student/RegisterStudent',
type: 'POST',
data: {
__RequestVerificationToken:token,
student: student,
},
dataType: 'JSON',
contentType:'application/x-www-form-urlencoded; charset=utf-8',
success: function (response) {
if (response.result == "Success") {
alert('Student Registered Succesfully!')
}
},
error: function (x,h,r) {
alert('Something went wrong')
}
})
};
Примечание. Тип контента должен быть 'application/x-www-form-urlencoded; charset=utf-8'
Я загрузил проект в Github; вы можете скачать и попробовать.
Я пробовал много рабочих мест, и не они работали для меня. Исключением было "Необходимое поле формы подделки" __RequestVerificationToken.
Что помогло мне в том, чтобы сменить форму .ajax на .post:
$.post(
url,
$(formId).serialize(),
function (data) {
$(formId).html(data);
});
contentType
дляapplication/json
потому что сервер ожидает, что параметр__RequestVerificationToken
будет частью полезной нагрузки POST-запроса с использованиемapplication/x-www-form-urlencoded
.