【问题标题】:ValidateAntiForgeryToken is failing from AJAX callValidateAntiForgeryToken 从 AJAX 调用失败
【发布时间】:2015-02-08 22:25:14
【问题描述】:

编辑:我已经尝试了更多的东西.. 看到这个问题的结尾更新

我正在尝试通过 AJAX 将一些数据与 AntiForgeryToken 一起从我的 MVC 应用程序中的页面传递到控制器。这不是我这样做的唯一地方,但这是它不工作的第一个地方。

我的代码的java端是:

var dirtyFields = [];

$('.DirtyField').each(function () {
    var newValue;

    if ($(this).is('select'))
        newValue = $(this).val();
    else if ($(this).is('input[type="text"]'))
        newValue = $(this).val();
    else
        newValue = ($(this).is(':checked')) ? 'true' : 'false';

    dirtyFields.push({
        FieldName: $(this).attr('name'),
        OldValue: $(this).attr('data-oldvalue'),
        NewValue: newValue
    });
});

var token = $("#__AjaxAntiForgeryForm input").val();
var dataObject =
    {
        __RequestVerificationToken: token,
        MaintUserId: $('#HiddenMaintUserID').val(),
        ChangedFields: dirtyFields
    };

$.ajax({
    url: '@Url.Action("SaveDataAction", "SomeController")',
    type: 'POST',
    contentType: 'json',
    data: dataObject,
    error: function (jqXHR, textStatus, errorThrown) {
        console.log(jqXHR);
        console.log(textStatus);
        console.log(errorThrown);
    }
}).done(function (result) {
    if (result.Success == 'true') {
        alert("User information was updated successfully!");
    }
    else {
        alert("Update failed!");
    }

在我的应用程序的控制器端是:

[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult SaveDataAction(SaveDataHelper dataObject)
{
    return Json(new { Success = "true" }, JsonRequestBehavior.DenyGet);
}

SaveDataHelper的定义是:

public class SaveDataHelper
{
    public int MaintUserID { get; set; }
    public List<DataItemHelper> ChangedFields { get; set; }
}

public class DataItemHelper
{
    public string FieldName { get; set; }
    public string OldValue  { get; set; }
    public string NewValue  { get; set; }
}

闯入我的javascript,在ajax调用时变量dataObject包含以下内容:

Object {__RequestVerificationToken: "Long-string-of-characters", MaintUserId: "9", ChangedFields: Array[1]}

ChangedFields 包含以下内容:

0: Object
    FieldName: "MiddleName"
    NewValue: ""
    OldValue: "S"

当我收到错误时,我在控制台中查看 jqXHR,并在 responseText 的顶部找到这个:

[HttpAntiForgeryException (0x80004005): The required anti-forgery form field &quot;__RequestVerificationToken&quot; is not present.]

此代码类似于我的应用程序中的所有代码。这里唯一的区别是我在 dataObject 中传递了一个数组(这是我第一次需要这样做)。

有什么建议吗?

编辑:由于关于 AntiForgery 表单的问题 .. 我(在 Chrome 中)去了查看页面源并从那里粘贴了 TOP 几行:

<form action="/Admin/UserMaint/9" id="__AjaxAntiForgeryForm" method="post"><input name="__RequestVerificationToken" type="hidden" value="long-string-of-charaacters-here" /></form><!DOCTYPE html>
<html>
<head>

所以 __AjaxAntiForgeryForm 是我页面上的第一件事.. 甚至在 html 标记之前。

这是我的视图中创建它的部分:

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

-- 编辑 12/10/2014 @ 2:31 PM EST --

在浏览了一些为此制作的 cmets,尤其是 @Pointy 的 cmets 之后,我尝试“扁平化”我的数据。我已将我的 dataObject 逻辑替换为以下内容:

var dataObject = {
    __RequestVerificationToken: token,
    UserId: '@Model.UserId',
    Field1Dirty: ($('#FieldID').hasClass('DirtyField')) ? 1 : 0,
    Field1Old: $('#FieldID').attr('data-oldvalue'),
    Field1New: $('#FieldID').val(),
    -- etc --
};

但是,即使使用完全平坦的数据,我仍然看到作为请求有效负载传递的数据,并且我在控制器中仍然没有得到任何信息。

-- 编辑 12/10/2014 @ 3:23 PM EST --

嗯..现在我完全迷路了。我将代码编辑为:

var dataObject = {
    UserId: '9'
};

它仍然作为请求有效负载发送。我不知道接下来要尝试什么。

【问题讨论】:

  • 您应该能够使用浏览器的开发人员工具准确查看 HTTP 请求的样子,以便验证您的页面是否发送正确的请求。
  • 请注意,var token = $("#__AjaxAntiForgeryForm input").val(); 将获取表单中第一个 &lt;input&gt; 元素的值。这真的是正确的做法吗?第一个 &lt;input&gt; 是其中包含您的安全令牌的那个吗?
  • 另外,正如@Pointy 所指出的,这将是获取其价值的正确方法:$("input[name=__RequestVerificationToken]").val();
  • 您是否检查过以确保传出的 HTTP 请求看起来正常?
  • 好吧,现在我看看您设置参数的方式,我认为这就是问题所在。由于这些嵌套对象,jQuery 无法将您的“dataObject”转换为查询字符串。

标签: javascript jquery ajax model-view-controller antiforgerytoken


【解决方案1】:

您拨出的$.ajax() 呼叫使用contentType 属性进行编码。这会影响 request 的内容类型,而不是响应。

我没有在 jQuery 源代码中找到影响发出的 HTTP 请求的位置和方式。

【讨论】:

  • 正如我在 cmets 中所说,这就是答案。我将dataType 错误地输入为contentType 并且无论我查看代码多少次都没有注意到它。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多