【问题标题】:How to test AntiForgeryToken in MVC4 with backbone Single Page Application如何使用主干单页应用程序在 MVC4 中测试 AntiForgeryToken
【发布时间】:2013-07-27 17:49:55
【问题描述】:

我无法让 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
    }

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

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

更新

@MrOggy85 提供的很棒的 stackoverflow 链接,其中包含更多信息。见How can i supply an AntiForgeryToken when posting JSON data using $.ajax?。我计划编写自己的 AntiForgery 测试,完成后会发布。

【问题讨论】:

    标签: .net asp.net-mvc-4 backbone.js single-page-application attributerouting


    【解决方案1】:

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

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

    此输入字段通常位于您的&lt;form&gt;-元素内,这意味着如果您提交该表单,它将附加到请求中。

    当此输入字段在您的表单之外或您没有提交表单时,就会出现此问题。不要害怕,有一个解决方案。属性[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 如何验证请求。如果您想使用其他内容类型,此解决方案How can i supply an AntiForgeryToken when posting JSON data using $.ajax? 建议将防伪令牌和 postdata 分隔在两个不同的参数中。

    【讨论】:

    • 嗨@MrOggy85。我们已经完全尝试了您编写的代码,但它失败了“所需的防伪表单字段“__RequestVerificationToken”不存在”。我们认为这是因为令牌不在 HttpRequest 的表单部分中。我们已验证令牌在响应中。你有上面的代码在应用程序中工作吗?也许我们错过了什么?
    • 您是否也将 [HttpPost] 放在了操作上(我有时会忘记这样做...)?是的,我的解决方案在一个活跃的 Web 应用程序中工作。
    • 感谢您的输入 MtOggy85,这非常有帮助,但我仍然有问题。至少您已经清楚它不必在请求的表单部分中。我已经更新了我的问题以包含我们在 api 中的代码。我只能假设 AttributeRouting 会导致问题,但我看不出是怎么回事。
    • 嗨 MrOggy85。一个想法 - 我们将数据作为 JSON 发送。我假设您使用的是 x-form-www-urlencoded - 您能确认一下吗?这可能是问题所在,尽管 MVC 绑定器应该解决这个问题。
    • 我明天会检查(几个小时后;))
    【解决方案2】:

    我不了解 AntiForgery,但是 Backbone 可以配置为 emulate RESTemulate JSON 以规避服务器的这种限制。

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

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

    【讨论】:

    • 嗨@mor,谢谢。我的问题是处理 MVC [ValidateAntiForgeryToken],如果我在 MVC 中使用标准方法,则需要所有数据作为表单提交返回。问题是,我应该改变 Backbone 来做到这一点,还是在 MVC 中实现我自己的令牌检查。我想知道是否有其他人在使用 MVC 构建单页应用程序时遇到过这个问题,以及他们对此做了什么。
    猜你喜欢
    • 2013-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多