在ASP.NET MVC的ajax中包含antiforgerytoken

OJ *_*eño 152 asp.net ajax asp.net-mvc csrf asp.net-mvc-3

我在使用ajax的AntiForgeryToken遇到了麻烦.我正在使用ASP.NET MVC 3.我在jQuery Ajax调用和Html.AntiForgeryToken()中尝试了解决方案.使用该解决方案,现在正在传递令牌:

var data = { ... } // with token, key is '__RequestVerificationToken'

$.ajax({
        type: "POST",
        data: data,
        datatype: "json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        url: myURL,
        success: function (response) {
            ...
        },
        error: function (response) {
            ...
        }
    });
Run Code Online (Sandbox Code Playgroud)

当我删除[ValidateAntiForgeryToken]属性只是为了查看数据(带有令牌)是否作为参数传递给控制器​​时,我可以看到它们正在被传递.但由于某种原因,A required anti-forgery token was not supplied or was invalid.当我放回属性时,消息仍会弹出.

有任何想法吗?

编辑

antiforgerytoken是在表单中生成的,但我没有使用提交操作来提交它.相反,我只是使用jquery获取令牌的值,然后尝试ajax发布.

这是包含令牌的表单,位于顶部母版页:

<form id="__AjaxAntiForgeryForm" action="#" method="post">
    @Html.AntiForgeryToken()
</form>
Run Code Online (Sandbox Code Playgroud)

Dar*_*rov 271

您错误地指定了contentTypeto application/json.

这是一个如何工作的例子.

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Index(string someValue)
    {
        return Json(new { someValue = someValue });
    }
}
Run Code Online (Sandbox Code Playgroud)

视图:

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

<div id="myDiv" data-url="@Url.Action("Index", "Home")">
    Click me to send an AJAX request to a controller action
    decorated with the [ValidateAntiForgeryToken] attribute
</div>

<script type="text/javascript">
    $('#myDiv').submit(function () {
        var form = $('#__AjaxAntiForgeryForm');
        var token = $('input[name="__RequestVerificationToken"]', form).val();
        $.ajax({
            url: $(this).data('url'),
            type: 'POST',
            data: { 
                __RequestVerificationToken: token, 
                someValue: 'some value' 
            },
            success: function (result) {
                alert(result.someValue);
            }
        });
        return false;
    });
</script>
Run Code Online (Sandbox Code Playgroud)

  • 你没有使用提交动作这一事实并没有改变我的答案.您需要做的就是订阅其他一些事件(按钮点击,锚点击或其他任何事情,只需阅读隐藏的字段值).就发送AJAX请求而言,您可以使用我的答案中提供的示例.您不应该将`contentType`用于`application/json`,因为服务器期望`__RequestVerificationToken`参数是使用`application/x-www-form-urlencoded`的POST请求有效负载的一部分. (13认同)
  • 最初的问题是关于contentType:'application/json'.对于常规的ajax帖子,包括表单帖子中的__RequestVerificationToken,显然会起作用,因为它就像一个普通的表单帖子.但是当你想发布json(因此内容类型)时,这似乎不起作用.所以这是一个错误地接受上述答案的情况. (2认同)

Max*_*Max 61

我做过的另一种(少了javascriptish)方法是这样的:

首先,一个Html助手

public static MvcHtmlString AntiForgeryTokenForAjaxPost(this HtmlHelper helper)
{
    var antiForgeryInputTag = helper.AntiForgeryToken().ToString();
    // Above gets the following: <input name="__RequestVerificationToken" type="hidden" value="PnQE7R0MIBBAzC7SqtVvwrJpGbRvPgzWHo5dSyoSaZoabRjf9pCyzjujYBU_qKDJmwIOiPRDwBV1TNVdXFVgzAvN9_l2yt9-nf4Owif0qIDz7WRAmydVPIm6_pmJAI--wvvFQO7g0VvoFArFtAR2v6Ch1wmXCZ89v0-lNOGZLZc1" />
    var removedStart = antiForgeryInputTag.Replace(@"<input name=""__RequestVerificationToken"" type=""hidden"" value=""", "");
    var tokenValue = removedStart.Replace(@""" />", "");
    if (antiForgeryInputTag == removedStart || removedStart == tokenValue)
        throw new InvalidOperationException("Oops! The Html.AntiForgeryToken() method seems to return something I did not expect.");
    return new MvcHtmlString(string.Format(@"{0}:""{1}""", "__RequestVerificationToken", tokenValue));
}
Run Code Online (Sandbox Code Playgroud)

这将返回一个字符串

__RequestVerificationToken:"P5g2D8vRyE3aBn7qQKfVVVAsQc853s-naENvpUAPZLipuw0pa_ffBf9cINzFgIRPwsf7Ykjt46ttJy5ox5r3mzpqvmgNYdnKc1125jphQV0NnM5nGFtcXXqoY3RpusTH_WcHPzH4S4l1PmB8Uu7ubZBftqFdxCLC5n-xT0fHcAY1"
Run Code Online (Sandbox Code Playgroud)

所以我们可以像这样使用它

$(function () {
    $("#submit-list").click(function () {
        $.ajax({
            url: '@Url.Action("SortDataSourceLibraries")',
            data: { items: $(".sortable").sortable('toArray'), @Html.AntiForgeryTokenForAjaxPost() },
            type: 'post',
            traditional: true
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

它似乎工作!

  • +1,很好.我只是将`@ Html.AntiForgeryTokenForAjaxPost`拆分为两个,以便一方面获取令牌名称,另一方面获取其值.否则语法高亮全部搞砸了.它最终会像这样(从返回的结果中删除单引号,这样它的行为就像任何MVC助手一样,例如@Url):`'@ Html.AntiForgeryTokenName':'@ Html.AntiForgeryTokenValue'` (5认同)
  • 尼特很好.有了这个你有ajax调用n cshtm文件....在我看来你不应该用razor mox js. (4认同)
  • 获取令牌值的更简洁方法是使用XElement.`XElement.Parse(antiForgeryInputTag)属性约( "值").Value` (4认同)
  • @transformer`var antiForgeryInputTag = helper.AntiForgeryToken().ToString(); 返回XElement.Parse(antiForgeryInputTag).Attribute("value").Value` (3认同)

Abo*_*azl 41

它很简单!当你@Html.AntiForgeryToken()在你的html代码中使用它意味着服务器已经签署了这个页面,并且从这个特定页面发送到服务器的每个请求都有一个标志,阻止黑客发送虚假请求.因此,要让服务器对此页面进行身份验证,您应该执行以下两个步骤:

1.发送一个名为的参数__RequestVerificationToken并获取其值使用代码如下:

<script type="text/javascript">
    function gettoken() {
        var token = '@Html.AntiForgeryToken()';
        token = $(token).val();
        return token;
   }
</script>
Run Code Online (Sandbox Code Playgroud)

例如,进行ajax调用

$.ajax({
    type: "POST",
    url: "/Account/Login",
    data: {
        __RequestVerificationToken: gettoken(),
        uname: uname,
        pass: pass
    },
    dataType: 'json',
    contentType: 'application/x-www-form-urlencoded; charset=utf-8',
    success: successFu,
});
Run Code Online (Sandbox Code Playgroud)

和步骤2只是装饰你的行动方法 [ValidateAntiForgeryToken]


Rua*_*urg 8

在Asp.Net Core中,您可以直接请求令牌,如记录所示

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf    
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Context).RequestToken;
    }
}
Run Code Online (Sandbox Code Playgroud)

并在javascript中使用它:

function DoSomething(id) {
    $.post("/something/todo/"+id,
               { "__RequestVerificationToken": '@GetAntiXsrfRequestToken()' });
}
Run Code Online (Sandbox Code Playgroud)

您可以添加推荐的全局过滤器,如记录所示

services.AddMvc(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
})
Run Code Online (Sandbox Code Playgroud)


ism*_*ski 6



        function DeletePersonel(id) {

                var data = new FormData();
                data.append("__RequestVerificationToken", "@HtmlHelper.GetAntiForgeryToken()");

                $.ajax({
                    type: 'POST',
                    url: '/Personel/Delete/' + id,
                    data: data,
                    cache: false,
                    processData: false,
                    contentType: false,
                    success: function (result) {

                    }
                });

        }
    

        public static class HtmlHelper
        {
            public static string GetAntiForgeryToken()
            {
                System.Text.RegularExpressions.Match value = System.Text.RegularExpressions.Regex.Match(System.Web.Helpers.AntiForgery.GetHtml().ToString(), "(?:value=\")(.*)(?:\")");
                if (value.Success)
                {
                    return value.Groups[1].Value;
                }
                return "";
            }
        }


Fra*_*oom 5

在Asp.Net MVC中,使用@Html.AntiForgeryToken()Razor时会创建一个隐藏的输入字段,其名称__RequestVerificationToken用于存储令牌。如果要编写AJAX实现,则必须自己获取此令牌并将其作为参数传递给服务器,以便可以对其进行验证。

步骤1:取得凭证

var token = $('input[name="`__RequestVerificationToken`"]').val();
Run Code Online (Sandbox Code Playgroud)

步骤2:在AJAX通话中传递令牌

function registerStudent() {

var student = {     
    "FirstName": $('#fName').val(),
    "LastName": $('#lName').val(),
    "Email": $('#email').val(),
    "Phone": $('#phone').val(),
};

$.ajax({
    url: '/Student/RegisterStudent',
    type: 'POST',
    data: { 
     __RequestVerificationToken:token,
     student: student,
        },
    dataType: 'JSON',
    contentType:'application/x-www-form-urlencoded; charset=utf-8',
    success: function (response) {
        if (response.result == "Success") {
            alert('Student Registered Succesfully!')

        }
    },
    error: function (x,h,r) {
        alert('Something went wrong')
      }
})
};
Run Code Online (Sandbox Code Playgroud)

注意:内容类型应为'application/x-www-form-urlencoded; charset=utf-8'

我已经在Github上上传了该项目;您可以下载并尝试。

https://github.com/lambda2016/AjaxValidateAntiForgeryToken