jQuery Ajax调用和Html.AntiForgeryToken()


207

根据我在互联网上的一些博客文章中所阅读的信息,我已经在我的应用程序中实施了缓解CSRF攻击的措施。这些帖子尤其是我实施的驱动力

基本上,这些文章和建议都说,为防止CSRF攻击,任何人都应实施以下代码:

1)[ValidateAntiForgeryToken]在接受POST Http动词的每个动作上添加

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SomeAction( SomeModel model ) {
}

2)在<%= Html.AntiForgeryToken() %>将数据提交到服务器的表单内添加帮助程序

<div style="text-align:right; padding: 8px;">
    <%= Html.AntiForgeryToken() %>
    <input type="submit" id="btnSave" value="Save" />
</div>

无论如何,在我的应用程序的某些部分中,我都使用jQuery将Ajax POST进行到服务器,而没有任何形式。例如,在发生这种情况时,我让用户单击图像来执行特定操作。

假设我有一个包含活动列表的表。我在表的列上有一幅图像,上面写着“将活动标记为已完成”,当用户单击该活动时,我正在执行Ajax POST,如以下示例所示:

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: {},
        success: function (response) {
            // ....
        }
    });
});

<%= Html.AntiForgeryToken() %>在这些情况下如何使用?我是否应该在Ajax调用的data参数中包括helper调用?

对不起,很长的帖子,非常感谢您的帮助

编辑

按照jayrdub的回答,我已经用下面的方式

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: {
            AddAntiForgeryToken({}),
            id: parseInt($(this).attr("title"))
        },
        success: function (response) {
            // ....
        }
    });
});

大卫·海登链接现在404,看来,他移居他的博客到一个新的CMS,但没有迁移过的所有旧的内容。

Answers:


252

我使用这样的简单js函数

AddAntiForgeryToken = function(data) {
    data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
    return data;
};

由于页面上的每个表单都将具有相同的令牌值,因此只需将这样的内容放在最顶层的母版页中

<%-- used for ajax in AddAntiForgeryToken() --%>
<form id="__AjaxAntiForgeryForm" action="#" method="post"><%= Html.AntiForgeryToken()%></form>  

然后在您的ajax调用中执行(已编辑,以匹配您的第二个示例)

$.ajax({
    type: "post",
    dataType: "html",
    url: $(this).attr("rel"),
    data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
    success: function (response) {
        // ....
    }
});

6
很好,我喜欢令牌获取的封装。
jball

2
@Lorenzo,将您的自定义数据放入的调用中AddAntiForgeryToken,如下所示:data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
jball 2010年

3
使用ajaxSend或覆盖ajax以始终增加data反伪造令牌的想法有多糟糕?也许添加一些检查以确保该地址url是发往您的服务器的。
ta.speot.13年

1
如果使用输出缓存,请当心。
Barbaros Alp 2014年

1
@SouhaiebBesbes验证令牌对于所有页面上的用户应该是相同的(它与设置并保持不变的cookie结合使用)。因此,每页是否有多个请求都没有关系,无论如何重新加载基本页都将是相同的。
JeremyWeir 2015年

29

我喜欢360Airwalk提供的解决方案,但可能会有所改进。

第一个问题是,如果$.post()使用空数据进行处理,jQuery不会添加Content-Type标头,在这种情况下,ASP.NET MVC无法接收和检查令牌。因此,您必须确保标题始终存在。

另一个改进是支持所有带有内容的 HTTP动词:POST,PUT,DELETE等。尽管您可能只在应用程序中使用POST,但最好有一个通用的解决方案,并验证任何动词收到的所有数据都具有防伪造性令牌。

$(document).ready(function () {
    var securityToken = $('[name=__RequestVerificationToken]').val();
    $(document).ajaxSend(function (event, request, opt) {
        if (opt.hasContent && securityToken) {   // handle all verbs with content
            var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
            // ensure Content-Type header is present!
            if (opt.contentType !== false || event.contentType) {
                request.setRequestHeader( "Content-Type", opt.contentType);
            }
        }
    });
});

1
+1您是对的,我还没有想到空的电话问题。感谢您的输入。您说对了,我们还没有在项目中使用delete / put。
360Airwalk 2012年

2
+1使我不必将函数添加到所有jQuery.Ajax调用中
Dragos Durlut

2
+1就像后人的注释一样,状态为jQuery的文档.ajaxSend()“自jQuery 1.8起,.ajaxSend()方法应仅附加到文档中。” api.jquery.com/ajaxsend
RJ Cuthbertson

1
@Bronx来自哪里options,最终if声明中列出了谁?谢谢。
hvaughan3 2016年

如果页面上有多个表单,请当心使用它。您将需要使用更具体的选择器调用而不是文档来设置beforeSend中的值。

22

我知道还有很多其他答案,但是这篇文章简洁明了,迫使您检查所有的HttpPost,而不仅仅是其中的一些:

http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/

它使用HTTP标头,而不是尝试修改表单集合。

服务器

//make sure to add this to your global action filters
[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
    public override void OnAuthorization( AuthorizationContext filterContext )
    {
        var request = filterContext.HttpContext.Request;

        //  Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {
            //  Ajax POSTs and normal form posts have to be treated differently when it comes
            //  to validating the AntiForgeryToken
            if (request.IsAjaxRequest())
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null
                    ? antiForgeryCookie.Value 
                    : null;

                AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute()
                    .OnAuthorization(filterContext);
            }
        }
    }
}

客户

var token = $('[name=__RequestVerificationToken]').val();
var headers = {};
headers["__RequestVerificationToken"] = token;

$.ajax({
    type: 'POST',
    url: '/Home/Ajax',
    cache: false,
    headers: headers,
    contentType: 'application/json; charset=utf-8',
    data: { title: "This is my title", contents: "These are my contents" },
    success: function () {
        ...
    },
    error: function () {
        ...
    }
});

4
您链接的文章中的属性也与Bronx的响应相结合,是针对此问题的最终DRY解决方案。
TugboatCaptain 2014年

2
很棒的发现。我对您的答案进行了编辑,以包括代码片段,因此答案可以独立存在,但我希望人们也能阅读本文的其余部分。这似乎是一个非常干净的解决方案。
Tim Medora 2014年

谢谢蒂姆,这是一个好主意,当链接失效并且答案变得一文不值时,它会令人沮丧。我已经根据所有新答案开始执行此操作。
活力2014年

这是MVC,WebAPI或.NetCore吗?我不能得到正确的命名空间的WebAPI 5
Myster

20

我在这里感觉像是一个高级的死灵法师,但这在4年后的MVC5中仍然是一个问题。

为了正确处理ajax请求,需要在ajax调用中将防伪令牌传递给服务器。将其集成到您的帖子数据和模型中是麻烦且不必要的。将令牌添加为自定义标头是干净且可重用的-您可以对其进行配置,因此您不必记住每次都要做。

有一个例外-不显眼的ajax不需要对ajax调用进行特殊处理。令牌照常在常规隐藏输入字段中传递。与常规POST完全相同。

_Layout.cshtml

在_layout.cshtml中,我有此JavaScript块。它没有将令牌写入DOM,而是使用jQuery从MVC帮助程序生成的隐藏输入文字中提取令牌。作为标题名称的Magic字符串在属性类中定义为常量。

<script type="text/javascript">
    $(document).ready(function () {
        var isAbsoluteURI = new RegExp('^(?:[a-z]+:)?//', 'i');
        //http://stackoverflow.com/questions/10687099/how-to-test-if-a-url-string-is-absolute-or-relative

        $.ajaxSetup({
            beforeSend: function (xhr) {
                if (!isAbsoluteURI.test(this.url)) {
                    //only add header to relative URLs
                    xhr.setRequestHeader(
                       '@.ValidateAntiForgeryTokenOnAllPosts.HTTP_HEADER_NAME', 
                       $('@Html.AntiForgeryToken()').val()
                    );
                }
            }
        });
    });
</script>

注意在beforeSend函数中使用了单引号-呈现的输入元素使用双引号将破坏JavaScript文字。

客户端JavaScript

执行此操作时,将调用上面的beforeSend函数,并且AntiForgeryToken将自动添加到请求标头中。

$.ajax({
  type: "POST",
  url: "CSRFProtectedMethod",
  dataType: "json",
  contentType: "application/json; charset=utf-8",
  success: function (data) {
    //victory
  }
});

服务器库

需要自定义属性来处理非标准令牌。这基于@viggity的解决方案,但是可以正确处理不引人注目的ajax。该代码可以藏在您的公共库中

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
    public const string HTTP_HEADER_NAME = "x-RequestVerificationToken";

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;

        //  Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {

            var headerTokenValue = request.Headers[HTTP_HEADER_NAME];

            // Ajax POSTs using jquery have a header set that defines the token.
            // However using unobtrusive ajax the token is still submitted normally in the form.
            // if the header is present then use it, else fall back to processing the form like normal
            if (headerTokenValue != null)
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null
                    ? antiForgeryCookie.Value
                    : null;

                AntiForgery.Validate(cookieValue, headerTokenValue);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute()
                    .OnAuthorization(filterContext);
            }
        }
    }
}

服务器/控制器

现在,您只需将属性应用于Action。更好的是,您可以将属性应用于控制器,所有请求都将得到验证。

[HttpPost]
[ValidateAntiForgeryTokenOnAllPosts]
public virtual ActionResult CSRFProtectedMethod()
{
  return Json(true, JsonRequestBehavior.DenyGet);
}

完美的解决方案,更加集中。谢谢
David Freire

您能否详细说明为什么只想为相对URL添加标题?那让我头疼。很好的解决方案!
MattM 2015年

relative确保标头仅在返回到您自己的服务器的请求上设置,因为ajax设置涵盖了所有用jquery发出的请求,因此我们不希望令牌在jsonp或CORS requet上发送。绝对网址也可能如此,但是相对地址必须保证是相同的域。

1
@WillD我喜欢您的解决方案,但被迫对其进行了一些修改。因为您选择$.ajaxSetup定义通用beforesend事件处理程序,所以可能会覆盖它。我找到了另一个解决方案,您可以在其中添加第二个处理程序,该处理程序也将被称为。效果很好,并且不会破坏您的实现。
Viper

是否有人拥有ASP.net 5版本的客户验证AntiForgery属性?此版本未在最新版本中编译!
罗伯·麦凯布

19

不要使用Html.AntiForgeryToken。而是,如在ASP.NET MVC应用程序防止跨站点请求伪造(CSRF)攻击中所述,从Web API 使用AntiForgery.GetTokensAntiForgery.Validate


对于将服务器模型类型模型绑定到已发布的AJAX JSON的控制器操作方法,使用适当的模型绑定器需要内容类型为“ application / json”。不幸的是,这排除了使用[ValidateAntiForgeryToken]属性所需的表单数据的可能性,因此您的方法是我发现使其起作用的唯一方法。我唯一的问题是,它仍然可以在Web场或多个Azure Web角色实例中工作吗?您@Edward,还是其他人知道这是否有问题?
理查德B

@爱德华·布雷(Edward Brey)您能详细说明为什么我们不应该使用它吗?
奥德斯2014年

4
@Odys:Html.AntiForgeryToken本质上没有什么问题,但是它有缺点:需要一个表单,需要jQuery,并假定未记录的Html.AntiForgeryToken实现细节。不过,在许多情况下都可以。我的声明“不要使用Html.AntiForgeryToken”可能过于强烈。我的意思是,它不打算与Web API一起使用,而更灵活的AntiForgery.GetTokens是。
爱德华·布雷

谢谢!我必须对其进行一些更改以使其适用于MVC5控制器,但这是解决方案
jao 2014年

3
它当然不需要表格。您只需要按名称解析DOM。使用jquery,我可以通过数据{__RequestVerificationToken:$(“ input [name = __ RequestVerificationToken]”)。val()}将其添加到我的数据对象中
安东尼·梅森,

16

我只是在当前项目中实现了这个实际问题。我为需要经过身份验证的用户的所有ajax-POST进行了此操作。

首先,我决定挂断我的jquery ajax调用,这样我就不会经常重复自己了。此javascript代码段可确保所有ajax(发布)调用均会将我的请求验证令牌添加到请求中。注意:.Net框架使用名称__RequestVerificationToken,因此我可以使用如下所示的标准Anti-CSRF功能。

$(document).ready(function () {
    var securityToken = $('[name=__RequestVerificationToken]').val();
    $('body').bind('ajaxSend', function (elm, xhr, s) {
        if (s.type == 'POST' && typeof securityToken != 'undefined') {
            if (s.data.length > 0) {
                s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
            else {
                s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
        }
    });
});

在您需要令牌可用于上述javascript的视图中,只需使用常见的HTML-Helper。您基本上可以在任何位置添加此代码。我将其放在if(Request.IsAuthenticated)语句中:

@Html.AntiForgeryToken() // you can provide a string as salt when needed which needs to match the one on the controller

在您的控制器中,只需使用标准的ASP.Net MVC反CSRF机制。我是这样做的(尽管我实际上使用过Salt)。

[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public JsonResult SomeMethod(string param)
{
    // do something
    return Json(true);
}

使用Firebug或类似工具,您可以轻松地看到POST请求现在如何附加了__RequestVerificationToken参数。


15

我认为您要做的就是确保POST请求中包含“ __RequestVerificationToken”输入。信息的另一半(即用户cookie中的令牌)已通过AJAX POST请求自动发送。

例如,

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: { 
            "__RequestVerificationToken":
            $("input[name=__RequestVerificationToken]").val() 
        },
        success: function (response) {
            // ....
        }
    });
});

1
经过数小时的尝试,从MVC(剃刀)页面中进行jQuery AJAX发布,这是所有对我有用的最简单的答案。只需在令牌后包括自己的数据字段(或我认为的viewModel)即可作为新数据(但要在原始数据对象内)。
拉尔夫·培根2013年

如果AJAX函数位于.html页面而不是Razor页面中,该如何实现呢?
建造者鲍勃(Bob)

如果您的html页面没有提供服务器,AntiForgeryToken那么无论如何都没有问题。如果确实如此(不确定您在那种情况下如何得到,但假设您是这样),那么上面的方法就可以了。如果您试图创建一个简单的网页,该网页将向服务器发送请求,请求该令牌,而服务器未生成该页面,那么您很不走运。从本质上讲,这就是AntiForgeryToken的意义所在
jball 2014年

6

您还可以执行以下操作:

$("a.markAsDone").click(function (event) {
    event.preventDefault();

    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: $('<form>@Html.AntiForgeryToken()</form>').serialize(),
        success: function (response) {
        // ....
        }
    });
});

这是使用Razor,但是如果您使用的是WebForms语法,那么也可以使用<%= %>标签


4

除了我对@JBall的回答在整个过程中对我有所帮助的评论之外,这是对我有用的最终答案。我正在使用MVC和Razor,并且正在使用jQuery AJAX提交表单,因此我可以使用一些新结果更新部分视图,而我不想进行完整的回发(和页面闪烁)。

@Html.AntiForgeryToken()照常添加内部表单。

我的AJAX提交按钮代码(即onclick事件)是:

//User clicks the SUBMIT button
$("#btnSubmit").click(function (event) {

//prevent this button submitting the form as we will do that via AJAX
event.preventDefault();

//Validate the form first
if (!$('#searchForm').validate().form()) {
    alert("Please correct the errors");
    return false;
}

//Get the entire form's data - including the antiforgerytoken
var allFormData = $("#searchForm").serialize();

// The actual POST can now take place with a validated form
$.ajax({
    type: "POST",
    async: false,
    url: "/Home/SearchAjax",
    data: allFormData,
    dataType: "html",
    success: function (data) {
        $('#gridView').html(data);
        $('#TestGrid').jqGrid('setGridParam', { url: '@Url.Action("GetDetails", "Home", Model)', datatype: "json", page: 1 }).trigger('reloadGrid');
    }
});

我留下了“成功”操作,它显示了如何更新包含MvcJqGrid的部分视图以及如何刷新它(非常强大的jqGrid网格,这是一个出色的MVC包装器)。

我的控制器方法如下所示:

    //Ajax SUBMIT method
    [ValidateAntiForgeryToken]
    public ActionResult SearchAjax(EstateOutlet_D model) 
    {
        return View("_Grid", model);
    }

我必须承认,不喜欢将整个表单的数据作为模型发布,但如果您需要这样做,那么这是一种可行的方法。MVC只是使数据绑定变得太容易了,所以我想这不是确定16个单个值(或类型弱的FormCollection)的好处。如果您知道的更好,请告诉我,因为我想生成健壮的MVC C#代码。


4

https://gist.github.com/scottrippey/3428114中发现了每个$ .ajax调用都非常巧妙的想法,它修改了请求并添加了令牌。

// Setup CSRF safety for AJAX:
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    if (options.type.toUpperCase() === "POST") {
        // We need to add the verificationToken to all POSTs
        var token = $("input[name^=__RequestVerificationToken]").first();
        if (!token.length) return;

        var tokenName = token.attr("name");

        // If the data is JSON, then we need to put the token in the QueryString:
        if (options.contentType.indexOf('application/json') === 0) {
            // Add the token to the URL, because we can't add it to the JSON data:
            options.url += ((options.url.indexOf("?") === -1) ? "?" : "&") + token.serialize();
        } else if (typeof options.data === 'string' && options.data.indexOf(tokenName) === -1) {
            // Append to the data string:
            options.data += (options.data ? "&" : "") + token.serialize();
        }
    }
});

我尝试了上面的其他几种方法,这就是为我解决的方法。
HostMyBus

但是,我确实必须添加if (options.contentType != false && options.contentType.indexOf('application/json') === 0) {以捕获未指定内容类型的Ajax调用
HostMyBus 19'Apr

3

1,定义功能从服务器获取令牌

@function
{

        public string TokenHeaderValue()
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
}

2.获取令牌并设置标头后再发送到服务器

var token = '@TokenHeaderValue()';    

       $http({
           method: "POST",
           url: './MainBackend/MessageDelete',
           data: dataSend,
           headers: {
               'RequestVerificationToken': token
           }
       }).success(function (data) {
           alert(data)
       });

3.在您处理Post / get的方法上对HttpRequestBase进行服务器验证

        string cookieToken = "";
        string formToken = "";
        string[] tokens = Request.Headers["RequestVerificationToken"].Split(':');
            if (tokens.Length == 2)
            {
                cookieToken = tokens[0].Trim();
                formToken = tokens[1].Trim();
            }
        AntiForgery.Validate(cookieToken, formToken);

1

我知道这个问题发布已经有一段时间了,但是我发现了非常有用的资源,该资源讨论了AntiForgeryToken的用法,并减少了使用上的麻烦。它还提供了jquery插件,可轻松在AJAX调用中包含防伪令牌:

ASP.NET MVC和AJAX的防伪请求食谱

我贡献不大,但是也许有人会觉得有用。


那个帖子就像一英里长!我确定这很好,但tl; dr
BritishDeveloper 2012年

1
太糟糕了,因为它很好地涵盖了主题。它不仅告诉您如何使用该功能,而且还说明了该功能可以解决的问题,并为您提供了正确理解如何正确使用它的环境。在安全性方面,我认为深入了解很重要。
slawek

2
如果重要的话,应该以鼓励人们阅读的方式编写;)
BritishDeveloper 2012年

1

首先在HTML中使用@ Html.AntiForgeryToken()

 $.ajax({
        url: "@Url.Action("SomeMethod", "SomeController")",
        type: 'POST',
        data: JSON.stringify(jsonObject),
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        async: false,
        beforeSend: function (request) {
            request.setRequestHeader("RequestVerificationToken", $("[name='__RequestVerificationToken']").val());
        },
        success: function (msg) {
            alert(msg);
        }

1

这是我见过的最简单的方法。注意:确保视图中有“ @ Html.AntiForgeryToken()”

  $("a.markAsDone").click(function (event) {
        event.preventDefault();
        var sToken = document.getElementsByName("__RequestVerificationToken")[0].value;
        $.ajax({
            url: $(this).attr("rel"),
            type: "POST",
            contentType: "application/x-www-form-urlencoded",
            data: { '__RequestVerificationToken': sToken, 'id': parseInt($(this).attr("title")) }
        })
        .done(function (data) {
            //Process MVC Data here
        })
        .fail(function (jqXHR, textStatus, errorThrown) {
            //Process Failure here
        });
    });

0

对360Airwalk解决方案的改进。这将反伪造令牌嵌入到javascript函数中,因此@ Html.AntiForgeryToken()不再需要包含在每个视图中。

$(document).ready(function () {
    var securityToken = $('@Html.AntiForgeryToken()').attr('value');
    $('body').bind('ajaxSend', function (elm, xhr, s) {
        if (s.type == 'POST' && typeof securityToken != 'undefined') {
            if (s.data.length > 0) {
                s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
            else {
                s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
        }
    });
});

0
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 "";
    }
}

0

我正在使用ajax发布来运行delete方法(可能来自visjs时间轴,但这并不相关)。这就是我的意思:

这是我的Index.cshtml

@Scripts.Render("~/bundles/schedule")
@Styles.Render("~/bundles/visjs")
@Html.AntiForgeryToken()

<!-- div to attach schedule to -->
<div id='schedule'></div>

<!-- div to attach popups to -->
<div id='dialog-popup'></div>

我在这里添加的只是@Html.AntiForgeryToken()使令牌显示在页面中

然后在我的ajax帖子中,我使用了:

$.ajax(
    {
        type: 'POST',
        url: '/ScheduleWorks/Delete/' + item.id,
        data: {
            '__RequestVerificationToken': 
            $("input[name='__RequestVerificationToken']").val()
              }
     }
);

它将从页面上刮下来的令牌值添加到发布的字段中

在此之前,我尝试将值放在标头中,但出现了相同的错误

随时发布改进。当然,这似乎是我可以理解的简单方法


0

好的,这里有很多文章,它们无一例外地帮助了我,谷歌的日子又来了又一阵子,而且我再也没想到要从头开始编写整个应用程序,然后我在Web.confg中注意到了这个小块。

 <httpCookies requireSSL="false" domain="*.localLookup.net"/>

现在,我不知道为什么添加它,但是后来我注意到了,它在调试模式下而不是在生产模式下被忽略(IE安装到IIS Somewhere)

对我来说,解决方案是2个选项之一,因为我不记得为什么添加了它,所以我不能确定其他因素不依赖它,其次,域名必须全部小写,而且TLD不像ive一样。在* .localLookup.net中

也许有帮助也许没有。我希望它能帮助某人


0

我发现的解决方案不是针对ASPX,而是针对Razor,而是一个可解决的问题。

我通过将AntiForgery添加到请求中来解决它。HTML Helper不会通过调用创建HTML ID

@Html.AntiForgeryToken()

为了将令牌添加到postrequest中,我刚刚使用jquery将AntiForgery id添加到了隐藏字段中:

$("input[name*='__RequestVerificationToken']").attr('id', '__AjaxAntiForgeryForm');

这导致控制器接受带有[ValidateAntiForgeryToken]属性的请求


-3

AntiforgeryToken仍然很痛苦,上面的例子对我来说都不是一个字一个字。那里太多了。所以我把它们都结合了。需要一个挂在iirc周围的表单中的@ Html.AntiforgeryToken

如此解决:

function Forgizzle(eggs) {
    eggs.__RequestVerificationToken =  $($("input[name=__RequestVerificationToken]")[0]).val();
    return eggs;
}

$.ajax({
            url: url,
            type: 'post',
            data: Forgizzle({ id: id, sweets: milkway }),
});

如有疑问,请添加更多的$符号

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.