Использование атрибута ValidateAntiForgeryToken с плагином Unobtrusive Ajax в ASP. NET Core - PullRequest
0 голосов
/ 23 марта 2020

У меня есть следующая форма:

<form asp-action="GetUsersAPICall" asp-controller="UsersObject" asp-antiforgery="true" data-ajax="true" data-ajax-method="get" data-ajax-mode="replace" data-ajax-update="#userSearchResult">
    Enter email or name to search for: <input type="text" id="query" name="query"/>

    <input type="submit" value="Search" />
</form>

<div id="userSearchResult"></div>

(Да, я понимаю, что я немного смешиваю ненавязчивый синтаксис AJAX с ASP. NET Помощниками основного тега).

У меня в контроллере есть следующий метод действия:

    [HttpPost]
    [Authorize(Roles = "PatchUser")]
    //[ValidateAntiForgeryToken]
    public async Task<IActionResult> PatchUserAPICall(UserPatchViewModel vm)
    {
        if (vm == null)
        {
            return BadRequest();
        }
        else if (!ModelState.IsValid)
        {
            return View(vm);
        }
        else
        {
            bool result = await vm.User.Update();

            if (result)
            {
                return RedirectToAction("Confirmation");
            }
            else
            {
                return StatusCode((int)HttpStatusCode.InternalServerError);
            }
        }
    }

Это прекрасно работает, если я не раскомментирую атрибут ValidateAntiForgeryToken.

Я видел примеры выполнение проверки для jQuery AJAX вызовов, но многие из них полагаются на отправку их в заголовках (например, в в этом Q & A ). Предположительно, это заставит ValidateAntiForgeryToken просто работать как положено (с некоторыми изменениями конфигурации в коде). Надеюсь, я не пропустил что-то очевидное, но я довольно долго искал и не могу найти, как на самом деле добавить заголовок в Unobtrusive AJAX, поэтому я даже не могу попробовать что-то подобное, чтобы увидеть, если это будет работать.

Я знаю, что вы можете сделать User.IsInRole("RoleName") в качестве альтернативы атрибуту Authorize. Есть ли способ отправить токен Anti-Forgery в качестве параметра и сделать это таким образом? Или есть способ отредактировать заголовки и сделать это таким образом? Или есть лучший способ сделать это, о котором я еще не думал?

В общем, есть ли способ отредактировать вызов Ajax до его отправки?

1 Ответ

1 голос
/ 28 апреля 2020

Прежде всего, ваш data-ajax-method="get" должен быть data-ajax-method="post". Это связано с тем, что использование asp -antiforgery = "true" добавит скрытый __RequestVerificationToken в вашу форму. Обычно это скрытое поле отправляется вместе с остальными данными вашей формы. Однако __RequestVerificationToken нельзя отправить в строке запроса (т. Е. GET), его необходимо отправить либо в заголовке, либо в теле (т. Е. POST). Если вы сделаете это изменение, скорее всего, это «просто сработает».

Однако также можно получить токен Antiforgery в заголовок запроса ajax. jquery ненавязчивый ajax не делает этого «из коробки», но добавить его нетрудно. В jquery .unobtrusive- ajax. js есть функция , asyncRequest(element, options){..} в конце этой функции - фактический jquery ajax вызов:

$.ajax(options);

Непосредственно перед этим вызовом в строке 143 в связанном коде введите следующее:

if (method === "POST") {
    var token = $("input[name='__RequestVerificationToken'][type='hidden']").val();
    if (token) {
        options.headers = { RequestVerificationToken: token };
    }
}

Это также может быть полезно, если вы делаете ajax POST, используя тег <a> для удаления или что-то еще:

@Html.AntiforgeryToken() //add the hidden antiforgery token, assuming you don't have a form tag.
<a href="#" data-ajax="true" data-ajax-method="post" 
  data-ajax-url="@Url.Action("Delete", new {Model.Id})" data-ajax-confirm="Are you sure?" 
  data-ajax-success="alert('success')">Delete This</a>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...