前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ASP.NET Core通过jQuery Ajax发送AntiForgeryToken

ASP.NET Core通过jQuery Ajax发送AntiForgeryToken

作者头像
Edi Wang
发布2019-07-08 19:29:15
1.5K0
发布2019-07-08 19:29:15
举报
文章被收录于专栏:汪宇杰博客汪宇杰博客

在ASP.NET Core中,如我我们希望用jQuery Ajax向服务器提交数据,并希望使用ValidateAntiForgeryToken标记,我们需要一些技巧。官方文档并没有说如何使用jQuery完成这个操作,我来演示给大家看看。

请首先阅读官方文档 https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.1

在我的实践中,实际场景和官方文档有所区别。

01

Token 生成

首先,我们仍然需要一个隐藏input去存储CSRF token,官网的代码如下

代码语言:javascript
复制
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Context).RequestToken;
    }
}
<input type="hidden" id="RequestVerificationToken" 
       name="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">

我用了个更简单的方法

代码语言:javascript
复制
@Html.AntiForgeryToken()

这样做有些好处。首先,显然省去了几行代码。不过,最重要的是,因为我已经自定义了CSRF的名称,就像这样

代码语言:javascript
复制
services.AddAntiforgery(options =>
{
    options.Cookie.Name = "X-CSRF-TOKEN-MOONGLADE";
    options.FormFieldName = "CSRF-TOKEN-MOONGLADE-FORM";
});

后台的Controller会使用这些名称去验证请求,并且,我不希望忘记更改每一处手写的代码。所以,换句话说,@Html.AntiForgeryToken()会基于我在Startup.cs中的定义生成HTML代码。如果哪天我改了antiforgery options的名称,我不需要担心哪个cshtml文件里忘了做对应的修改。

代码语言:javascript
复制
<input name="CSRF-TOKEN-MOONGLADE-FORM" type="hidden" value="CfDJ8BBX[...]">

02

Controller和Action

这和普通的Action没有啥区别,只要加上[ValidateAntiForgeryToken]标记就够了

代码语言:javascript
复制
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
[Route("delete")]
public IActionResult Delete(Guid pingbackId)
{
    ...
}

03

jQuery 代码

这里是真正关键的地方,官网文档里的JavaScript代码值是给请求加了header

代码语言:javascript
复制
document.addEventListener('DOMContentLoaded', function() {
    document.getElementById("antiforgery").onclick = function () {
        xhttp.open('POST', '@Url.Action("Antiforgery", "Home")', true);
        xhttp.setRequestHeader("RequestVerificationToken", 
            document.getElementById('RequestVerificationToken').value);
        xhttp.send();
    }
});

我们在jQuery中同样也能实现

代码语言:javascript
复制
$.ajax({
    ...
    headers: {
        "CSRF-TOKEN-MOONGLADE-FORM": $('input[name="CSRF-TOKEN-MOONGLADE-FORM"]').val()
    },
    ...
});

然而,这并不能工作。我还没搞明白为啥,但是我有了解决方法,就是把CSRF的值放到提交的数据中去。

我使用$.extend方法将“CSRF-TOKEN-MOONGLADE-FORM”加入

代码语言:javascript
复制
var pData = $.extend({ pingbackId: pingbackId }, 
{ "CSRF-TOKEN-MOONGLADE-FORM": $('input[name="CSRF-TOKEN-MOONGLADE-FORM"]').val()});

现在整段Ajax代码看起来就像这样

代码语言:javascript
复制
$(function () {
    $(".btn-delete").click(function () {
        deletePingback($(this).data("pingbackid"));
    });
});
function deletePingback(pingbackId) {
    $("#span-processing-" + pingbackId).show();
    var pData = $.extend({ pingbackId: pingbackId }, { "CSRF-TOKEN-MOONGLADE-FORM": $('input[name="CSRF-TOKEN-MOONGLADE-FORM"]').val()});
    $.ajax({
        type: "POST",
        url: "pingback/delete",
        headers: {
            "CSRF-TOKEN-MOONGLADE-FORM": $('input[name="CSRF-TOKEN-MOONGLADE-FORM"]').val()
        },
        data: pData,
        success: function (data) {
            $("#pingback-box-" + data).slideUp();
        },
        dataType: "json"
    });
}

现在你的Ajax请求可以被后台MVC的action成功验证了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-09-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 汪宇杰博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档