3

我在让 Microsoft 的 MVC[ValidateAntiForgeryToken]与使用 Marionette & Backbone 编写的单页应用程序 (SPA) 一起工作时遇到问题。问题似乎是 MVC[ValidateAntiForgeryToken]方法无法看到我们作为 JSON 的一部分发送的令牌。我们认为这是因为令牌必须在回复的表单部分中,但 MrOggy85 说这不是问题(请参阅下面的答案)。

代码在我的 api 控制器中,它使用AttributeRouting,我们认为这是导致问题的原因。一个典型的动作如下所示:

    // POST api/vizschemes/
    [POST("")]
    [Authorize(Roles = "...some role...")]
    [ValidateAntiForgeryToken]
    public ActionResult Add(CreateUpdateSmVizSchemeDto dto,  ICreateSmVizScheme service)
    {
       ... code to update the VizScheme and return json
    }

有没有其他人克服过这个?很多谷歌搜索发现了帖子中的评论“ ASP.NET MVC 通过 AntiForgery 类和 [ValidateAntiForgeryToken] 属性提供了对防伪令牌的内置支持。目前,此功能未内置在 Web API 中。但是, (KnockoutJS) 模板包括 Web API 的自定义实现。 ”。这表明他们自己编写,我可以做到。

有没有其他人遇到过这个问题,如果是这样,您是如何解决的?我是否遗漏了一些明显的东西,还是应该只编写自己的 ValidateAntiForgeryToken 方法?您的意见将不胜感激。

更新

@MrOggy85 提供的很棒的 stackoverflow 链接,其中包含更多信息。请参阅使用 $.ajax 发布 JSON 数据时如何提供 AntiForgeryToken?. 我计划编写自己的 AntiForgery 测试,并在完成后发布。

4

2 回答 2

2

当您@Html.AntiForgeryToken()在视图中使用帮助器时,这是实际的 HTML 结果:

<input name="__RequestVerificationToken" type="hidden" 
value="{ long cryptic code }">

此输入字段通常位于您的<form>-element 内,这意味着如果您提交该表单,它将附加到请求中。

当此输入字段在您的表单之外或您没有提交表单时,就会出现问题。不要害怕,有一个解决方案。该属性[ValidateAntiForgeryToken]告诉服务器查找名称为“__RequestVerificationToken”的密钥。让我们给服务器它想要的东西!

首先,得到那个值!

var antiforgeytoken = $('input[name=__RequestVerificationToken]').val();

其次,将其附加到您的 AJAX 请求(我使用 jQuery)

$.ajax({
  url: 'something/something',
  type: 'POST',
  contentType: 'application/x-www-form-urlencoded; charset=UTF-8', // Default
  data: { 'somekey': 'someval', 
          '__RequestVerificationToken', antiforgeytoken }
});

现在您的服务器很高兴,您也很高兴!

更新:
内容类型很重要,因为 MVC Binder 如何验证请求。如果您想使用其他内容类型,此解决方案如何在使用 $.ajax 发布 JSON 数据时提供 AntiForgeryToken?建议将防伪令牌和 postdata 分开在两个不同的参数中。

于 2013-08-01T07:48:05.797 回答
0

我不了解 AntiForgery,但可以将 Backbone 配置为模拟 REST模拟 JSON以规避服务器的这种限制。

Backbone.emulateHTTP = true;
Backbone.emulateJSON = true;

这将告诉 Backbone 仅使用andPOST方法delete()并将update()数据发送为application/x-www-form-urlencoded而不是application/json.

于 2013-07-28T13:17:11.807 回答