验证防伪密钥不适用于 ajax post

Validate Anti forgery key not working with ajax post

我尝试将验证防伪令牌与 ajax post 请求一起使用,但响应是找不到根元素。 我删除了它完美运行的防伪令牌。

这是我的代码: javascript;

  function Save() {
        let GroupName = GetElementValue("GroupName");
        let GroupId = GetElementValue("GroupId");
        var Group = {
            __RequestVerificationToken: gettoken(),
            GroupId: :1",
            GroupName: "My Group Name"
        };

        if (IsFormValid("GroupForm")) {
            AjaxPost("/Groups/AddGroup", Group).done(function () {
                GetGroups();
            });
        }
    }


     function gettoken() {
        var token = '@Html.AntiForgeryToken()';
        token = $(token).val();
        return token;
   }

function AjaxPost(url, data) {
    return $.ajax({
        type: "post",
        contentType: "application/json;charset=utf-8",
        dataType: "json",
        responseType: "json",
        url: url,
        data: JSON.stringify(data)
    });
}

我也试过这个:

$.ajax({
    type: "POST",
    url: "/Groups/AddGroup",
    data: {
        __RequestVerificationToken: gettoken(),
        GroupId: 1,
        GroupName: "please work"
    },
    dataType: 'json',
    contentType: 'application/x-www-form-urlencoded; charset=utf-8',

});

这是后端:

  [HttpPost]
        [ValidateAntiForgeryToken]
        public void AddGroup([FromBody] GroupView Group)
        {
            if (Group.GroupName.Trim().Length>0)
            {
                bool existed = _context.Groups.Any(x => x.GroupName.ToLower().TrimEnd().Equals(Group.GroupName.ToLower().TrimEnd()));
                if (!existed)
                {
                    Groups group = new Groups()
                    {
                        GroupName = Group.GroupName
                    };
                    _context.Groups.AddAsync(group);
                    _context.SaveChanges();
                    int? groupId = group.GroupId;
                }
            }
        }

这是我的 Class GroupView

public class GroupView
{
    public string GroupId { get; set; }
    public string GroupName { get; set; }
}

我想使用我正常发送串行令牌和我的数据的方法, 我怎样才能让它工作? 任何帮助!

在 ASP.NET Core 中,您可以通过表单或 headers 传递防伪令牌。所以我可以为您推荐 2 个解决方案。

解决方案一. Headers

为了让框架从 headers 读取令牌,您需要配置 AntiforgeryOptions 并将 HeaderName 设置为非 null 值。将此代码添加到 Startup.cs

//or if you omit this configuration 
//HeaderName will be "RequestVerificationToken" by default
services.AddAntiforgery(options =>
{
    options.HeaderName = "X-CSRF-TOKEN"; //may be any other valid header name
});

并在 AJAX

中传递防伪令牌
function Save() {
    //..
    //no need to set token value in group object
    var Group = {
        GroupId: "1",
        GroupName: "My Group Name"
    };
    //..
}

function AjaxPost(url, data) {
    return $.ajax({
        type: "post",
        contentType: "application/json;charset=utf-8",
        dataType: "json",
        responseType: "json",
        headers: {
            "X-CSRF-TOKEN": gettoken()
        },
        url: url,
        data: JSON.stringify(data)
});

方案二.表格

您已经尝试通过表单传递令牌,但没有成功。为什么?原因是 IAntiforgeryTokenStore 的默认实现(用于从请求中读取令牌)无法从 json 中读取防伪令牌,而是将其作为表单数据读取。如果你想让它工作,那么不要 stringify 请求数据并从 $.ajax 调用中删除 contentType 属性。 JQuery 将为您分别设置合适的内容类型和序列化数据。

//all other original code is unchanged, group needs to contain a token
function AjaxPost(url, data) {
    return $.ajax({
        type: "post",
        dataType: "json",
        responseType: "json",
        url: url,
        data: data
});

在这种情况下,您还需要从操作参数中删除 [FromBody] 属性,让模型绑定器正确绑定模型

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult AddGroup(GroupView group)

对于 FromBody,它将绑定来自 application/json 的模型,但 CSRF 不会从 body 读取令牌。

对于最简单的方法,您可以添加 header 和 RequestVerificationToken

Controller

[HttpPost("/Groups/AddGroup")]
[ValidateAntiForgeryToken]
public void AddGroup([FromBody] GroupView Group)
{
}

Client

<script type="text/javascript">
    $(document).ready(function(){
        var Group = {
            __RequestVerificationToken: gettoken(),
            GroupId: 1,
            GroupName: "My Group Name"
        };

        AjaxPost("/Groups/AddGroup", Group).done(function () {
            GetGroups();
        });

    });
    function gettoken() {
        var token = '@Html.AntiForgeryToken()';
        token = $(token).val();
        return token;
    }

    function AjaxPost(url, data) {
        return $.ajax({
            type: "post",
            contentType: "application/json;charset=utf-8",
            dataType: "json",
            responseType: "json",
            url: url,
            headers: {
                "RequestVerificationToken": gettoken()
            },
            data: JSON.stringify(data)
        });
    }
</script>