Выполняет ASP.NET Core 5 API ожидает __RequestVerificationToken xor Заголовок RequestVerificationToken при использовании [ValidateAntiForgeryToken]?

#asp.net-core #asp.net-core-webapi #asp.net-core-5.0

#asp.net-core #asp.net-core-webapi #asp.net-core-5.0

Вопрос:

Я не могу найти ответ в документах. Ожидает ли ASP .NET Core 5 __RequestVerificationToken RequestVerificationToken заголовок or в методе Http Post, когда метод API был оформлен [ValidateAntiForgeryToken] . Я видел обе версии в примерах, но не знаю, какая из них правильная.

Комментарии:

1. вы не знаете, но вы можете легко попробовать, и тогда вы узнаете это сами. Я не очень уверен в .net 5 (потому что у меня не было возможности попробовать), но заголовок требуется (по умолчанию) в asp.net core 2.2 is RequestVerificationToken , поэтому он может быть сохранен без изменений в более поздних версиях.

Ответ №1:

Пожалуйста, ознакомьтесь с этой статьей.

В ASP.NET Core 2.0 или более поздней версии, для традиционных приложений на основе HTML (таких как MVC и Razor application) FormTagHelper вводит токены защиты от подделки в элементы формы HTML, он добавит скрытое поле формы, подобное следующему:

 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
 

Но в современных приложениях и SPA на основе JavaScript многие запросы выполняются программно. Эти AJAX-запросы могут использовать другие методы (такие как заголовки запросов или файлы cookie) для отправки токена.

Если файлы cookie используются для хранения токенов аутентификации и проверки подлинности запросов API на сервере, CSRF является потенциальной проблемой. Если для хранения токена используется локальное хранилище, уязвимость CSRF может быть устранена, поскольку значения из локального хранилища не отправляются автоматически на сервер с каждым запросом. Таким образом, использование локального хранилища для хранения токена защиты от подделки на клиенте и отправка токена в качестве заголовка запроса является рекомендуемым подходом.

Итак, в такого рода приложениях он будет вводить Microsoft.AspNetCore.Защита от подделки.Я запускаю службу в представление и вызываю GetAndStoreTokens, затем использую скрытое поле (с именем RequestVerificationToken) для хранения токена проверки. Код, как показано ниже:

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

<input type="hidden" id="RequestVerificationToken" 
       name="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">
 

Используя этот метод, скрытое поле добавляется самостоятельно, поэтому вы можете настроить имя скрытого поля и значение идентификатора.

После этого, если мы настроим параметры защиты от подделки при запуске.Настраивает службы, такие как: пользовательское имя заголовка для RequestVerificationToken.

 services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");  //configure the antiforgery service to look for the X-CSRF-TOKEN header. To prevent the cross-site request forgery.
 

Затем, для современных приложений на основе JavaScript, мы могли бы использовать скрипт для добавления заголовка запроса:

         document.getElementById("antiforgery").onclick = function () {
            xhttp.open('POST', '@Url.Action("Antiforgery", "Home")', true);
            xhttp.setRequestHeader("XSRF-TOKEN",
                document.getElementById('RequestVerificationToken').value); //get the requestverification token.
            xhttp.send();
        }
 

Для традиционных приложений на основе HTML мы могли бы использовать следующий скрипт:

             $.ajax({
                type: "POST",
                url: "/Survey/Create",
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("XSRF-TOKEN",
                        $('input:hidden[name="__RequestVerificationToken"]').val());
                },
                data: { "CategoryName": $("#CategoryName").val(), "CategoryID": $("#CategoryID").val() },
                success: function (response) {
                    alert(response);
                },
                failure: function (response) {
                    alert(response.responseText);
                },
                error: function (response) {
                    alert(response.responseText);
                }
            });