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

时间:2019-02-26 09:41:37

标签: javascript c# asp.net-core model-view-controller asp.net-ajax

added我尝试在ajax post请求中使用validate antiforgery令牌,但响应是未找到root元素。 我删除了防伪令牌,它可以正常工作。

这是我的代码:  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

这是我的班级GroupView

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

我想使用正常发送带有数据的串行令牌的方法, 我如何使它起作用? 任何帮助!

3 个答案:

答案 0 :(得分:2)

在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
});

此外,您还需要从操作参数中删除[FromBody]属性,以使模型绑定程序在这种情况下正确地绑定模型

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

答案 1 :(得分:1)

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

以最简单的方式,您可以使用CSRF添加标题。

RequestVerificationToken

Controller

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

Client

答案 2 :(得分: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将令牌发送给您的控制器:

$.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',

});