【问题标题】:Using ValidateAntiForgeryToken attribute with Unobtrusive Ajax plugin in ASP.NET Core在 ASP.NET Core 中将 ValidateAntiForgeryToken 属性与 Unobtrusive Ajax 插件一起使用
【发布时间】:2020-07-04 04:41:27
【问题描述】:

我有以下表格:

<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>

(是的,我确实意识到我正在将 Unobtrusive AJAX 语法与 ASP.NET Core 标签助手混合在一起)。

我的控制器中有以下操作方法:

    [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 调用进行验证的示例,但其中许多依赖于在标头中发送它(例如在 this Q&A 中)。据推测,这将使ValidateAntiForgeryToken 按预期工作(在代码中进行一些配置更改)。希望我没有遗漏一些明显的东西,但是我已经搜索了很多并且找不到如何在 Unobtrusive AJAX 中实际添加标题,所以我什至无法尝试类似的东西来看看它是否会工作。

我知道您可以使用User.IsInRole("RoleName") 来替代Authorize 属性。有没有办法将防伪令牌作为参数发送并这样做?或者有没有办法编辑标题并这样做?或者有没有我还没有想到的更好的方法?

一般来说,有什么方法可以在发送 Ajax 调用之前对其进行编辑?

【问题讨论】:

  • 您的GetUsersAPICall 操作是什么?另外,您如何将UserPatchViewModel 传递给PatchUserAPICall 操作?
  • 你不能在正文中发送它(通过隐藏输入或其他方式)吗? Ruard van Elburg 在这里做这样的事情:stackoverflow.com/questions/40530474/…
  • @Ritzelprimpf 虽然那里的 OP 正在使用 jQuery,但如果我“手动”执行整个 Ajax 调用,我会看到如何做到这一点。我仍然有点不清楚如何使用 Unobtrusive Ajax 做类似的事情。

标签: c# asp.net-core .net-core asp.net-core-3.1 unobtrusive-ajax


【解决方案1】:

首先,您的data-ajax-method="get" 应该是data-ajax-method="post"。这是因为您使用 asp-antiforgery="true" 会将隐藏的 __RequestVerificationToken 添加到您的表单中。通常,此隐藏字段与您的其他表单数据一起提交。但是,__RequestVerificationToken 不能在查询字符串(即 GET)中提交,它必须在标头或正文中(即 POST)提交。如果您进行此更改,整个事情可能会“正常工作”。

但是,也可以将 Antiforgery 令牌放入 ajax 请求的标头中。 jquery unobtrustive 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 };
    }
}

如果您正在使用 &lt;a&gt; 标记进行 ajax POST 进行删除或其他操作,这也很有用:

@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>

【讨论】:

    猜你喜欢
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-07
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    相关资源
    最近更新 更多