验证Anti伪造密钥不适用于ajax帖子

问题描述 投票:0回答:3

addedI尝试使用带有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;
                }
            }
        }

Here is the parameter passing perfectly

这是我的班级组视图

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

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

javascript c# asp.net-core model-view-controller asp.net-ajax
3个回答
3
投票

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

解决方案1.标题

为了让框架从头部读取令牌,您需要配置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)
});

解决方案2.表格

您已经尝试通过表单传递令牌但它不起作用。为什么?原因是IAntiforgeryTokenStore的默认实现(用于从请求中读取令牌)无法从json读取防伪令牌,而是将其作为表单数据读取。如果你想使它工作,那么不要stringify请求数据并从contentType调用中删除$.ajax属性。 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
});

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

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

1
投票

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

最简单的方法是,您可以使用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>

0
投票

你必须在你的VIEW中在这样的表单中生成令牌:

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" 
}))
{
 @Html.AntiForgeryToken()
}

然后你可以在你的Javascript中获取令牌的价值,如下所示:

var form = $('#__AjaxAntiForgeryForm');
var token = $('input[name="__RequestVerificationToken"]', form).val();

最后,您可以通过AJAX将令牌发送到您的CONTROLLER,如下所示:

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

});
© www.soinside.com 2019 - 2024. All rights reserved.