jQuery Ajax дзвонить і Html.AntiForgeryToken ()


207

Я застосував у своїй програмі пом'якшення нападів на КСВР після інформації, яку я прочитав у публікації щоденника в Інтернеті. Зокрема, ці посади були рушієм мого впровадження

В основному в цих статтях та рекомендаціях написано, що для запобігання нападу на КСВР будь-хто повинен застосовувати наступний код:

1) Додайте до [ValidateAntiForgeryToken]кожної дії, що приймає дієслово POST Http

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SomeAction( SomeModel model ) {
}

2) Додайте <%= Html.AntiForgeryToken() %>помічник всередину форм, який подає дані на сервер

<div style="text-align:right; padding: 8px;">
    <%= Html.AntiForgeryToken() %>
    <input type="submit" id="btnSave" value="Save" />
</div>

Так чи інакше, в деяких частинах мого додатка я роблю Ajax POST з jQuery на сервер, не маючи жодної форми. Це відбувається, наприклад, коли я дозволяю користувачеві натиснути на зображення, щоб зробити певну дію.

Припустимо, у мене є таблиця із переліком діяльності. У мене є зображення на стовпці таблиці з написом "Позначити активність як завершену", і коли користувач натискає на цю діяльність, я виконую POST Ajax як у наступному зразку:

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: {},
        success: function (response) {
            // ....
        }
    });
});

Як я можу використовувати <%= Html.AntiForgeryToken() %>в цих випадках? Чи потрібно включати виклик помічника всередині параметра даних виклику Ajax?

Вибачте за довгий пост і дуже дякую за допомогу

Редагувати :

Відповідно до відповіді jayrdub, я використовував наступний спосіб

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: {
            AddAntiForgeryToken({}),
            id: parseInt($(this).attr("title"))
        },
        success: function (response) {
            // ....
        }
    });
});

Посилання David Hayden Тепер помилки 404, здається , що він мігрував свій блог на нову CMS, але не мігрували весь старий контент через.

Відповіді:


252

Я використовую просту функцію js, як це

AddAntiForgeryToken = function(data) {
    data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
    return data;
};

Оскільки кожна форма на сторінці матиме однакове значення для маркера, просто покладіть щось подібне на свою головну головну сторінку

<%-- used for ajax in AddAntiForgeryToken() --%>
<form id="__AjaxAntiForgeryForm" action="#" method="post"><%= Html.AntiForgeryToken()%></form>  

Потім у вашому виклику Ajax зробіть (відредагований відповідно до вашого другого прикладу)

$.ajax({
    type: "post",
    dataType: "html",
    url: $(this).attr("rel"),
    data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
    success: function (response) {
        // ....
    }
});

6
Приємно, мені подобається інкапсуляція отримання лексеми.
jball

2
@Lorenzo, розмістіть власні користувальницькі дані всередині дзвінка AddAntiForgeryTokenтак:data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
jball

3
Наскільки поганою ідеєю було б використовувати ajaxSendабо переосмислити ajaxзавжди доповнення dataза допомогою маркера проти підробки? Можливо, додайте перевірку, щоб переконатися, що urlце призначено для вашого сервера.
ta.speot.is

1
Будьте обережні, якщо ви використовуєте кеш-вихід.
Barbaros Alp

1
@SouhaiebBesbes маркер перевірки повинен бути однаковим для користувача на всіх сторінках (він працює в поєднанні з печивом, яке встановлено і залишається таким же). Тож не має значення, чи є кілька запитів на сторінку, це буде те саме, якщо базова сторінка все одно перезавантажується.
JeremyWeir

29

Мені подобається рішення, яке надає 360Airwalk, але воно може трохи покращитися.

Перша проблема полягає в тому, що якщо ви робите $.post()порожні дані, jQuery не додає Content-Typeзаголовка, і в цьому випадку ASP.NET MVC не отримує та перевіряє маркер. Таким чином, ви повинні забезпечити, що заголовок завжди є.

Ще одне вдосконалення - підтримка всіх дієслів HTTP із вмістом : POST, PUT, DELETE тощо. Хоча ви можете використовувати лише POSTs у своїй програмі, краще мати загальне рішення та переконатися, що всі дані, які ви отримуєте з будь-яким дієсловом, мають анти-підробку лексема.

$(document).ready(function () {
    var securityToken = $('[name=__RequestVerificationToken]').val();
    $(document).ajaxSend(function (event, request, opt) {
        if (opt.hasContent && securityToken) {   // handle all verbs with content
            var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
            // ensure Content-Type header is present!
            if (opt.contentType !== false || event.contentType) {
                request.setRequestHeader( "Content-Type", opt.contentType);
            }
        }
    });
});

1
+1 ви маєте рацію, я не замислювався над проблемою порожнього поштового дзвінка. дякую за вклад. Ви мали рацію щодо того, що ми ще не використовуємо delete / put у нашому проекті.
360Airwalk

2
+1, щоб врятувати мене від необхідності додавати функцію до всіх дзвінків jQuery.Ajax
Dragos Durlut

2
+1 Так само як примітка до нащадків, документація jQuery для .ajaxSend()штатів "Станом на jQuery 1.8 метод .ajaxSend () повинен бути доданий лише до документа". api.jquery.com/ajaxsend
RJ Cuthbertson

1
@Bronx Звідки optionsпоходить, що вказано у заключному ifвикладі? Дякую.
hvaughan3

Обережно використовуйте це, якщо у вас є кілька форм на сторінці. Вам потрібно буде встановити значення в beforeSend за допомогою більш конкретного вибору вибору, а не для документа.
Dan

22

Я знаю, що є багато інших відповідей, але ця стаття є приємною і стислою і змушує вас перевірити всі ваші HttpPosts, а не лише деякі з них:

http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/

Він використовує заголовки HTTP замість спроб змінити колекцію форм.

Сервер

//make sure to add this to your global action filters
[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
    public override void OnAuthorization( AuthorizationContext filterContext )
    {
        var request = filterContext.HttpContext.Request;

        //  Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {
            //  Ajax POSTs and normal form posts have to be treated differently when it comes
            //  to validating the AntiForgeryToken
            if (request.IsAjaxRequest())
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null
                    ? antiForgeryCookie.Value 
                    : null;

                AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute()
                    .OnAuthorization(filterContext);
            }
        }
    }
}

Клієнт

var token = $('[name=__RequestVerificationToken]').val();
var headers = {};
headers["__RequestVerificationToken"] = token;

$.ajax({
    type: 'POST',
    url: '/Home/Ajax',
    cache: false,
    headers: headers,
    contentType: 'application/json; charset=utf-8',
    data: { title: "This is my title", contents: "These are my contents" },
    success: function () {
        ...
    },
    error: function () {
        ...
    }
});

4
Атрибут статті, який ви пов’язали занадто у поєднанні з відповіддю Бронкса, є остаточним рішенням цієї проблеми.
TugboatCaptain

2
Чудова знахідка. Я відредагував вашу відповідь, щоб включити фрагменти коду, щоб відповідь стояла самостійно, але сподіваюся, що люди прочитають і решту статті. Це, здається, дуже чисте рішення.
Тім Медора

дякую Тіму, це відмінна ідея, її засмучує, коли посилання загине і відповідь стає нікчемною. Я почав це робити на всіх своїх нових відповідях.
бадьорість

Це MVC, WebAPI чи .NetCore? Я не можу отримати правильні простори імен для WebAPI 5
Myster

20

Я відчуваю себе як просунутий некромант, але це все ще проблема 4 роки потому в MVC5.

Щоб правильно обробляти запити ajax, маркер анти-підробки потрібно передавати серверу під час викликів ajax. Інтегрувати їх у свої дані та моделі публікацій безладно і непотрібно. Додавання токена як спеціального заголовка є чистим і багаторазовим - і ви можете налаштувати його так, що вам не потрібно пам’ятати це робити кожного разу.

Є виняток - ненав’язливий аякс не потребує спеціального лікування для викликів аякса. Маркер передається, як зазвичай, у звичайному полі прихованого введення. Точно так само, як і звичайний POST.

_Layout.cshtml

У _layout.cshtml у мене є цей блок JavaScript. Він не записує маркер у DOM, а використовує jQuery для отримання його з прихованого вхідного літералу, який генерує MVC Helper. Рядок Magic, який є ім'ям заголовка, визначається як константа в класі атрибутів.

<script type="text/javascript">
    $(document).ready(function () {
        var isAbsoluteURI = new RegExp('^(?:[a-z]+:)?//', 'i');
        //http://stackoverflow.com/questions/10687099/how-to-test-if-a-url-string-is-absolute-or-relative

        $.ajaxSetup({
            beforeSend: function (xhr) {
                if (!isAbsoluteURI.test(this.url)) {
                    //only add header to relative URLs
                    xhr.setRequestHeader(
                       '@.ValidateAntiForgeryTokenOnAllPosts.HTTP_HEADER_NAME', 
                       $('@Html.AntiForgeryToken()').val()
                    );
                }
            }
        });
    });
</script>

Зверніть увагу на використання одиничних лапок у функції beforeSend - введений елемент, що надається, використовує подвійні лапки, які порушували б буквальний JavaScript.

Клієнтський JavaScript

Коли це виконується, функція beforeSend викликається вище, і AntiForgeryToken автоматично додається до заголовків запитів.

$.ajax({
  type: "POST",
  url: "CSRFProtectedMethod",
  dataType: "json",
  contentType: "application/json; charset=utf-8",
  success: function (data) {
    //victory
  }
});

Серверна бібліотека

Для обробки нестандартного маркера потрібен спеціальний атрибут. Це ґрунтується на рішенні @ viggity, але правильно поводиться з ненав’язливим ajax. Цей код можна заховати у вашій загальній бібліотеці

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
    public const string HTTP_HEADER_NAME = "x-RequestVerificationToken";

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;

        //  Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {

            var headerTokenValue = request.Headers[HTTP_HEADER_NAME];

            // Ajax POSTs using jquery have a header set that defines the token.
            // However using unobtrusive ajax the token is still submitted normally in the form.
            // if the header is present then use it, else fall back to processing the form like normal
            if (headerTokenValue != null)
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null
                    ? antiForgeryCookie.Value
                    : null;

                AntiForgery.Validate(cookieValue, headerTokenValue);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute()
                    .OnAuthorization(filterContext);
            }
        }
    }
}

Сервер / контролер

Тепер ви просто застосуєте атрибут до вашої дії. Ще краще ви можете застосувати атрибут до свого контролера, і всі запити будуть підтверджені.

[HttpPost]
[ValidateAntiForgeryTokenOnAllPosts]
public virtual ActionResult CSRFProtectedMethod()
{
  return Json(true, JsonRequestBehavior.DenyGet);
}

Ідеальне рішення, набагато більш централізоване. Спасибі
Девід Фрейр

Чи можете ви пояснити більш детально, чому ви хочете додати заголовок лише для відносних URL-адрес? Це перейшло мені над головою. Чудове рішення!
MattM

відносний гарантує, що заголовок встановлюється лише на запити, що повертаються на ваш власний сервер, оскільки налаштування ajax охоплює всі запити, зроблені за допомогою jquery, ми не хочемо, щоб маркер надсилався на запити jsonp або CORS. Це може бути справедливо і для абсолютних URL-адрес, але відносно вони гарантовано однакові.
Буде D

1
@WillD мені сподобалось ваше рішення, але змушений був його трохи змінити. Оскільки ви вирішите $.ajaxSetupвизначити загальний beforesendобробник подій, можливо, ви перезапишете його. Я знайшов інше рішення, де можна додати другий обробник, який також буде викликаний. Працює чудово і не порушує вашу реалізацію.
Гадюка

Хто-небудь має версію ASP.net 5 версії клієнта атрибуту AntiForgery? Ця версія не компілюється в останню версію!
Роб Маккей

19

Не використовуйте Html.AntiForgeryToken . Натомість використовуйте AntiForgery.GetTokens та AntiForgery.Validate з веб-API, як описано у попередженні нападів підписів на міжміські сайти (CSRF) у програмі ASP.NET MVC .


Для методів дії контролера, які моделюють зв'язок типу моделі сервера з розміщеним AJAX JSON, тип вмісту як "application / json" необхідний для використання належного модельного в'яжучого. На жаль, це виключає використання даних форми, необхідних атрибуту [ValidateAntiForgeryToken], тому ваш метод - єдиний спосіб, коли я міг би знайти його для роботи. Єдине моє запитання: чи все ще це працює у веб-фермі чи декількох екземплярах веб-ролей Azure? Ви @Edward чи хтось ще знає, чи це проблема?
Річард Б

@Edward Brey Чи можете ви, будь ласка, детальніше пояснити, чому ми не повинні його використовувати?
Одіс

4
@Odys: З Html.AntiForgeryToken немає нічого суттєвого, але він має і недоліки: вимагає форми, вимагає jQuery і передбачає недокументовані деталі реалізації Html.AntiForgeryToken. І все-таки це добре в багатьох контекстах. Моє твердження "Не використовуй Html.AntiForgeryToken", ймовірно, виходить занадто сильним. Моє значення полягає в тому, що він не призначений для використання з Web API, тоді як більш гнучка AntiForgery.GetTokens.
Едвард Брей

Дякую! Мені довелося трохи змінити його, щоб він працював для контролера MVC5, але це було рішення
яо

3
Це, звичайно, не вимагає форми. Вам просто потрібно розібрати для нього DOM по імені. Використовуючи jquery, я можу додати його всередині свого об'єкта даних за допомогою даних {__RequestVerificationToken: $ ("input [name = __ RequestVerificationToken]"). Val ()}
Ентоні Мейсон

16

Я щойно реалізував цю актуальну проблему в своєму поточному проекті. Я зробив це для всіх ajax-POST, яким потрібен аутентифікований користувач.

Спершу я вирішив зачепити свої дзвінки на ajax jquery, щоб не повторювати себе занадто часто. цей фрагмент javascript гарантує, що всі виклики ajax (post) додадуть до запиту мітку підтвердження мого запиту. Примітка: ім'я __RequestVerificationToken використовується рамкою .Net, щоб я міг використовувати стандартні функції Anti-CSRF, як показано нижче.

$(document).ready(function () {
    var securityToken = $('[name=__RequestVerificationToken]').val();
    $('body').bind('ajaxSend', function (elm, xhr, s) {
        if (s.type == 'POST' && typeof securityToken != 'undefined') {
            if (s.data.length > 0) {
                s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
            else {
                s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
        }
    });
});

У своїх переглядах, де вам потрібно, щоб маркер був доступний для вищевказаного JavaScript, просто використовуйте загальний HTML-помічник. Ви можете в основному додати цей код де завгодно. Я розмістив його в операторі if (Request.IsAuthentication):

@Html.AntiForgeryToken() // you can provide a string as salt when needed which needs to match the one on the controller

У своєму контролері просто використовуйте стандартний механізм ASP.Net MVC Anti-CSRF. Я зробив це так (хоча я фактично використовував Сіль).

[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public JsonResult SomeMethod(string param)
{
    // do something
    return Json(true);
}

За допомогою Firebug або подібного інструменту ви можете легко побачити, як у ваші запити POST тепер додається параметр __RequestVerificationToken.


15

Я думаю, що все, що вам потрібно зробити, - це забезпечити, щоб вхід "__RequestVerificationToken" був включений у запит POST. Інша половина інформації (тобто маркер у файлі cookie користувача) вже надсилається автоматично із запитом AJAX POST.

Наприклад,

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: { 
            "__RequestVerificationToken":
            $("input[name=__RequestVerificationToken]").val() 
        },
        success: function (response) {
            // ....
        }
    });
});

1
Після багатьох годин експериментуючи з розміщенням jQuery AJAX на сторінці MVC (Razor), це була найпростіша відповідь з усіх, що працювали на мене. Просто додайте свої власні поля даних (або, я думаю, viewModel) після лексеми як новий фрагмент даних (але всередині оригінального об'єкта даних).
Ральф Бекон

Як би я реалізував це, якщо функція AJAX знаходилась на .html сторінці, а не на сторінці Razor?
Bob the Builder

Якщо на вашій html-сторінці немає сервера AntiForgeryToken, все одно суперечить. Якщо так (не впевнений, як ви отримуєте його в такому випадку, але якщо припустити, що ви є), то вищезгадане спрацювало б чудово. Якщо ви намагаєтеся створити просто веб-сторінку, яка надсилатиме запит на сервер, який очікує вказаний маркер, а сервер не генерував цю сторінку, то вам не пощастить. Це, по суті, пункт AntiForgeryToken ...
jball

6

Ви також можете це зробити:

$("a.markAsDone").click(function (event) {
    event.preventDefault();

    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: $('<form>@Html.AntiForgeryToken()</form>').serialize(),
        success: function (response) {
        // ....
        }
    });
});

Це використовується Razor, але якщо ви використовуєте WebFormsсинтаксис, ви можете так само добре використовувати <%= %>теги


4

На додаток до мого коментаря проти відповіді @ JBall, який допоміг мені на цьому шляху, це остаточна відповідь, яка працює для мене. Я використовую MVC та Razor, і я надсилаю форму за допомогою jQuery AJAX, щоб я міг оновити частковий вигляд деякими новими результатами, і я не хотів робити повне поштове повідомлення (і мерехтіння сторінки).

Додайте @Html.AntiForgeryToken()всередину форми як завжди.

Мій код кнопки подання AJAX (тобто подія onclick):

//User clicks the SUBMIT button
$("#btnSubmit").click(function (event) {

//prevent this button submitting the form as we will do that via AJAX
event.preventDefault();

//Validate the form first
if (!$('#searchForm').validate().form()) {
    alert("Please correct the errors");
    return false;
}

//Get the entire form's data - including the antiforgerytoken
var allFormData = $("#searchForm").serialize();

// The actual POST can now take place with a validated form
$.ajax({
    type: "POST",
    async: false,
    url: "/Home/SearchAjax",
    data: allFormData,
    dataType: "html",
    success: function (data) {
        $('#gridView').html(data);
        $('#TestGrid').jqGrid('setGridParam', { url: '@Url.Action("GetDetails", "Home", Model)', datatype: "json", page: 1 }).trigger('reloadGrid');
    }
});

Дію "успіх" я покинув, оскільки він показує, як оновлюється частковий вигляд, який містить MvcJqGrid і як він оновлюється (дуже потужна сітка jqGrid і це блискуча оболонка MVC для неї).

Мій метод контролера виглядає так:

    //Ajax SUBMIT method
    [ValidateAntiForgeryToken]
    public ActionResult SearchAjax(EstateOutlet_D model) 
    {
        return View("_Grid", model);
    }

Я маю визнати, що не є фанатом розміщення даних цілої форми як моделі, але якщо вам потрібно це зробити, це працює одним із способів. MVC просто робить прив'язку даних занадто простою, тому замість того, щоб підміняти 16 окремих значень (або слабко набраний FormCollection) це добре, я думаю. Якщо ви краще знаєте, будь ласка, повідомте мене, як я хочу створити надійний код MVC C #.


4

знайшов цю дуже розумну ідею з https://gist.github.com/scottrippey/3428114 для кожного виклику $ .ajax, він змінює запит і додає маркер.

// Setup CSRF safety for AJAX:
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    if (options.type.toUpperCase() === "POST") {
        // We need to add the verificationToken to all POSTs
        var token = $("input[name^=__RequestVerificationToken]").first();
        if (!token.length) return;

        var tokenName = token.attr("name");

        // If the data is JSON, then we need to put the token in the QueryString:
        if (options.contentType.indexOf('application/json') === 0) {
            // Add the token to the URL, because we can't add it to the JSON data:
            options.url += ((options.url.indexOf("?") === -1) ? "?" : "&") + token.serialize();
        } else if (typeof options.data === 'string' && options.data.indexOf(tokenName) === -1) {
            // Append to the data string:
            options.data += (options.data ? "&" : "") + token.serialize();
        }
    }
});

Я спробував кілька інших альтернатив вище, саме це вирішило це для мене.
HostMyBus

Однак мені довелося додати if (options.contentType != false && options.contentType.indexOf('application/json') === 0) {дзвінки Ajax, які не вказали тип вмісту
HostMyBus

3

1. Визначте функцію для отримання токена з сервера

@function
{

        public string TokenHeaderValue()
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
}

2. Отримайте маркер і встановіть заголовок перед відправкою на сервер

var token = '@TokenHeaderValue()';    

       $http({
           method: "POST",
           url: './MainBackend/MessageDelete',
           data: dataSend,
           headers: {
               'RequestVerificationToken': token
           }
       }).success(function (data) {
           alert(data)
       });

3. Валідація Onserver на HttpRequestBase за методом, який ви обробляєте Post / get

        string cookieToken = "";
        string formToken = "";
        string[] tokens = Request.Headers["RequestVerificationToken"].Split(':');
            if (tokens.Length == 2)
            {
                cookieToken = tokens[0].Trim();
                formToken = tokens[1].Trim();
            }
        AntiForgery.Validate(cookieToken, formToken);

1

Я знаю, що минуло час, коли це питання було розміщено, але я знайшов дійсно корисний ресурс, який обговорює використання AntiForgeryToken і робить його менш клопітним у використанні. Він також надає плагін jquery для легкого включення маркера антифабрикатів у дзвінки AJAX:

Рецепти запиту проти підробки для ASP.NET MVC та AJAX

Я не дуже сприяю, але, можливо, хтось вважатиме це корисним.


Цей пост довгий, як миля! Я впевнений, що це чудово, але т.
Д.

1
Дуже погано, бо це чудово висвітлює тему. Він не тільки розповідає, як користуватися функцією, але пояснює, яку проблему вона виправляє, і дає вам контекст, щоб зрозуміти, як правильно ним користуватися. Що стосується безпеки, я думаю, що глибоке розуміння важливе.
slawek

2
Якщо це важливо, його слід писати так, що спонукає людей читати його;)
BritishDeveloper

1

перше використання @ Html.AntiForgeryToken () в html

 $.ajax({
        url: "@Url.Action("SomeMethod", "SomeController")",
        type: 'POST',
        data: JSON.stringify(jsonObject),
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        async: false,
        beforeSend: function (request) {
            request.setRequestHeader("RequestVerificationToken", $("[name='__RequestVerificationToken']").val());
        },
        success: function (msg) {
            alert(msg);
        }

1

Ось найпростіший спосіб, який я бачив. Примітка. Переконайтеся, що у вашому представленні є "@ Html.AntiForgeryToken ()"

  $("a.markAsDone").click(function (event) {
        event.preventDefault();
        var sToken = document.getElementsByName("__RequestVerificationToken")[0].value;
        $.ajax({
            url: $(this).attr("rel"),
            type: "POST",
            contentType: "application/x-www-form-urlencoded",
            data: { '__RequestVerificationToken': sToken, 'id': parseInt($(this).attr("title")) }
        })
        .done(function (data) {
            //Process MVC Data here
        })
        .fail(function (jqXHR, textStatus, errorThrown) {
            //Process Failure here
        });
    });

0

Невелике вдосконалення до рішення 360Airwalk. Це додає маркер Anti Forgery в функцію javascript, тому @ Html.AntiForgeryToken () більше не потрібно включати в кожен перегляд.

$(document).ready(function () {
    var securityToken = $('@Html.AntiForgeryToken()').attr('value');
    $('body').bind('ajaxSend', function (elm, xhr, s) {
        if (s.type == 'POST' && typeof securityToken != 'undefined') {
            if (s.data.length > 0) {
                s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
            else {
                s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
        }
    });
});

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

0

Я використовую пост ajax для запуску методу видалення (трапляється з часової шкали visjs, але це не є релевантним). Ось що я:

Це мій Index.cshtml

@Scripts.Render("~/bundles/schedule")
@Styles.Render("~/bundles/visjs")
@Html.AntiForgeryToken()

<!-- div to attach schedule to -->
<div id='schedule'></div>

<!-- div to attach popups to -->
<div id='dialog-popup'></div>

Все, що я тут додав, - @Html.AntiForgeryToken()це зробити маркер на сторінці

Тоді в своєму аякс-посаді я використав:

$.ajax(
    {
        type: 'POST',
        url: '/ScheduleWorks/Delete/' + item.id,
        data: {
            '__RequestVerificationToken': 
            $("input[name='__RequestVerificationToken']").val()
              }
     }
);

Що додає значення токена, зішкребте зі сторінки, до опублікованих полів

До цього я намагався ввести значення в заголовки, але в мене виникла така ж помилка

Сміливо публікуйте вдосконалення. Це, звичайно, здається простим підходом, який я можу зрозуміти


0

Добре багато публікацій тут, жодна з них не допомогла мені, дні та дні google, і все ще більше я не дійшов до того, що wr написав весь додаток з нуля, і тоді я помітив цей маленький самородок у своєму Web.confg

 <httpCookies requireSSL="false" domain="*.localLookup.net"/>

Тепер я не знаю, чому я додав його, однак я з тих пір помітив, його ігнорують у режимі налагодження, а не у режимі виробництва (IE встановлено IIS десь)

Для мене рішення було одним із 2 варіантів, тому що я не пам'ятаю, чому я додав це, я не можу бути впевнений, що інші речі від цього не залежать, а по-друге, доменне ім'я повинно бути всім малим регістром і TLD не так, як я робив в * .localLookup.net

Можливо, це допомагає, можливо, це не так. Я сподіваюся, що це комусь допомагає


0

Знайдене нами рішення не для ASPX, а для Razor, але цілком спірне питання.

Я вирішив це, додавши до запиту AntiForgery. HTML Helper не створює HTML-ідентифікатор під час виклику

@Html.AntiForgeryToken()

Для того, щоб додати маркер до післязапиту, я просто додав ідентифікатор AntiForgery до прихованого поля за допомогою jquery:

$("input[name*='__RequestVerificationToken']").attr('id', '__AjaxAntiForgeryForm');

Це змусило контролер прийняти запит з атрибутом [ValidateAntiForgeryToken]


-3

AntiforgeryToken - це все ще біль, жоден із наведених вище прикладів не працював слово для слова. Занадто багато для них є. Тож я поєднав їх усіх. Потрібно @ Html.AntiforgeryToken у формі, що висить навколо iirc

Вирішено так:

function Forgizzle(eggs) {
    eggs.__RequestVerificationToken =  $($("input[name=__RequestVerificationToken]")[0]).val();
    return eggs;
}

$.ajax({
            url: url,
            type: 'post',
            data: Forgizzle({ id: id, sweets: milkway }),
});

Якщо ви сумніваєтесь, додайте більше знаків $

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.