Включить antiforgerytoken в ajax post ASP.NET MVC

У меня возникают проблемы с 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>

Ответ 1

Вы неправильно указали 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>

Ответ 2

Другой (менее javascriptish) подход, который я сделал, выглядит примерно так:

Во-первых, html-помощник

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
        });
    });
});

И это работает!

Ответ 3

Это так просто! когда вы используете @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]

Ответ 4

В Asp.Net Core вы можете запросить токен напрямую, как задокументировано:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf    
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Context).RequestToken;
    }
}

И используйте его в JavaScript:

function DoSomething(id) {
    $.post("/something/todo/"+id,
               { "__RequestVerificationToken": '@GetAntiXsrfRequestToken()' });
}

Вы можете добавить рекомендуемый глобальный фильтр , как описано в документации:

services.AddMvc(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
})

Ответ 5


        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 "";
            }
        }

Ответ 6

В 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; вы можете скачать и попробовать.

https://github.com/lambda2016/AjaxValidateAntiForgeryToken

Ответ 7

Я знаю, что это старый вопрос. Но я все равно добавлю свой ответ, может помочь кому-то вроде меня.

Если вы не хотите обрабатывать результат после действия контроллера, например вызов метода 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>

Ответ 8

Я пробовал много рабочих мест, и не они работали для меня. Исключением было "Необходимое поле формы подделки" __RequestVerificationToken.

Что помогло мне в том, чтобы сменить форму .ajax на .post:

$.post(
    url,
    $(formId).serialize(),
    function (data) {
        $(formId).html(data);
    });

Ответ 9

Не стесняйтесь использовать функцию ниже:

function AjaxPostWithAntiForgeryToken(destinationUrl, successCallback) {
var token = $('input[name="__RequestVerificationToken"]').val();
var headers = {};
headers["__RequestVerificationToken"] = token;
$.ajax({
    type: "POST",
    url: destinationUrl,
    data: { __RequestVerificationToken: token }, // Your other data will go here
    dataType: "json",
    success: function (response) {
        successCallback(response);
    },
    error: function (xhr, status, error) {
       // handle failure
    }
});

}

Ответ 10

В контроллере аккаунта:

    // POST: /Account/SendVerificationCodeSMS
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public JsonResult SendVerificationCodeSMS(string PhoneNumber)
    {
        return Json(PhoneNumber);
    }

В представлении:

$.ajax(
{
    url: "/Account/SendVerificationCodeSMS",
    method: "POST",
    contentType: 'application/x-www-form-urlencoded; charset=utf-8',
    dataType: "json",
    data: {
        PhoneNumber: $('[name="PhoneNumber"]').val(),
        __RequestVerificationToken: $('[name="__RequestVerificationToken"]').val()
    },
    success: function (data, textStatus, jqXHR) {
        if (textStatus == "success") {
            alert(data);
            // Do something on page
        }
        else {
            // Do something on page
        }
    },
    error: function (jqXHR, textStatus, errorThrown) {
        console.log(textStatus);
        console.log(jqXHR.status);
        console.log(jqXHR.statusText);
        console.log(jqXHR.responseText);
    }
});

Важно установить contentType на 'application/x-www-form-urlencoded; charset=utf-8' или просто опустить contentType из объекта...

Ответ 11

Токен не будет работать, если он был предоставлен другим контроллером. Например. это не будет работать, если представление было возвращено контроллером Accounts, но вы POST на контроллер Clients.