35

我有一个表格帖子,它一直给我一个防伪令牌错误。

这是我的表格:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.EditorFor(m => m.Email)
    @Html.EditorFor(m => m.Birthday)
    <p>
        <input type="submit" id="Go" value="Go" />
    </p>
}

这是我的操作方法:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Join(JoinViewModel model)
{
    //a bunch of stuff here but it doesn't matter because it's not making it here
}

这是 web.config 中的 machineKey:

<system.web>
  <machineKey validationKey="mykey" decryptionKey="myotherkey" validation="SHA1" decryption="AES" />
</system.web>

这是我得到的错误:

A required anti-forgery token was not supplied or was invalid.

我读过在 HttpContext 上更改用户将使令牌无效,但这不会发生在这里。我的加入操作上的 HttpGet 只返回视图:

[HttpGet]
public ActionResult Join()
{
    return this.View();
}

所以我不确定发生了什么。我四处搜索,一切似乎都表明它是 machineKey 更改(应用程序周期)或用户/会话更改。

还有什么可能发生的?我该如何解决这个问题?

4

11 回答 11

33

我不知道您是否意味着您能够按需获取错误 - 或者您在日志中看到它,但无论如何,这是一种保证防伪令牌错误的方法。

等等...

  • 确保您已注销,然后输入您的登录信息
  • 双击登录按钮
  • 你会得到 :

提供的防伪令牌用于用户“”,但当前用户是“XXX@yahoo.com”。

(现在我将假设这个确切的错误消息在 MVC4 中发生了变化,并且这基本上是你得到的相同消息)。

那里有很多人仍然双击所有内容 - 这很糟糕! 我刚醒来后才发现这一点,所以我真的不知道这是如何通过测试的。您甚至不必双击 - 如果按钮无响应,当我第二次单击时我自己也会遇到此错误。

我刚刚删除了验证属性。我的网站始终是 SSL,我并不太担心风险。我只需要它现在就可以工作。另一种解决方案是使用 javascript 禁用按钮。

这可以在 MVC4 初始安装模板上复制。

于 2013-02-23T21:40:58.890 回答
19

在 Adam 的帮助下,我将 MVC 源添加到我的项目中,并且能够看到有很多情况会导致相同的错误。

以下是用于验证防伪令牌的方法:

    public void Validate(HttpContextBase context, string salt) {
        Debug.Assert(context != null);

        string fieldName = AntiForgeryData.GetAntiForgeryTokenName(null);
        string cookieName = AntiForgeryData.GetAntiForgeryTokenName(context.Request.ApplicationPath);

        HttpCookie cookie = context.Request.Cookies[cookieName];
        if (cookie == null || String.IsNullOrEmpty(cookie.Value)) {
            // error: cookie token is missing
            throw CreateValidationException();
        }
        AntiForgeryData cookieToken = Serializer.Deserialize(cookie.Value);

        string formValue = context.Request.Form[fieldName];
        if (String.IsNullOrEmpty(formValue)) {
            // error: form token is missing
            throw CreateValidationException();
        }
        AntiForgeryData formToken = Serializer.Deserialize(formValue);

        if (!String.Equals(cookieToken.Value, formToken.Value, StringComparison.Ordinal)) {
            // error: form token does not match cookie token
            throw CreateValidationException();
        }

        string currentUsername = AntiForgeryData.GetUsername(context.User);
        if (!String.Equals(formToken.Username, currentUsername, StringComparison.OrdinalIgnoreCase)) {
            // error: form token is not valid for this user
            // (don't care about cookie token)
            throw CreateValidationException();
        }

        if (!String.Equals(salt ?? String.Empty, formToken.Salt, StringComparison.Ordinal)) {
            // error: custom validation failed
            throw CreateValidationException();
        }
    }

我的问题是它将身份用户名与表单令牌的用户名进行比较的情况。就我而言,我没有设置用户名(一个为空,另一个为空字符串)。

虽然我怀疑很多人会遇到同样的情况,但希望其他人会发现查看正在检查的潜在条件很有用。

于 2011-04-25T16:22:19.167 回答
9

AntiForgeryToken 还会检查您的登录用户凭据是否未更改——这些凭据也在 cookie 中加密。AntiForgeryConfig.SuppressIdentityHeuristicChecks = true您可以通过在 global.asax.cs 文件中 进行设置来关闭它。

于 2014-02-10T14:31:41.533 回答
8

您应该防止双重表单提交。我使用如下代码防止此类问题:

$('#loginForm').on('submit',function(e){
    var $form = $(this);

    if (!$form.data('submitted') && $form.valid()) {
      // mark it so that the next submit can be ignored
      $form.data('submitted', true);
      return;
    }

    // form is invalid or previously submitted - skip submit
    e.preventDefault();
});

或者

$('#loginForm').submit(function () {
    $(this).find(':submit').attr('disabled', 'disabled'); 
});
于 2014-06-19T12:02:24.367 回答
3

我刚刚遇到了一个@Html.AntiForgeryToken()被调用两次的问题,因此 Anti-forger 令牌在 HTTP Post 有效负载中被搞砸了。

于 2012-12-13T23:34:50.817 回答
2

您是在一台服务器上还是在网络场上?如果是单个服务器,请在 web.config 中注释掉您的 machineKey 元素,然后作为基本起点重试。任何改变?另外——你能想到你的 cookie 被清除或过期的任何原因吗——它们也是正常工作所必需的。

于 2011-04-24T01:21:36.363 回答
2

在禁用提交按钮之前,有必要检查表单是否有效。

<script type="text/javascript">
//prevent double form submission
$('form', '#loginForm').submit(function () {
    if ($(this).valid()) {
        $(this).find(':submit').attr('disabled', 'disabled');
    }
});

于 2015-10-02T19:31:49.647 回答
1

另一件可能要检查的事情对我来说是什么导致了这个错误:我@Html.AntiForgeryToken()的一个表格中有两个。

一旦被删除,问题就消失了。

于 2014-11-01T18:18:32.560 回答
1

当我不得不将我的应用程序迁移到新机器时,我也遇到了同样的问题。不明白为什么会突然出现这个错误,但感觉肯定是和迁移有关,于是开始研究通过aspnet_reqsql注册数据库的问题,排除后才知道一定是和应用注册有关果然我在类似的地方找到了答案。我还在旅途中发现有两种方法可以解决这个问题。

  1. ASP.NET 自动为每个应用程序生成一个加密密钥并将该密钥存储在 HKCU 注册表配置单元中。当应用程序在服务器场上迁移或访问时,这些密钥不匹配,因此方法一是向 web.config 添加唯一的机器密钥。机器密钥可以从 IIS 管理控制台生成并添加到 web.config 部分

    的<machineKey的validationKey = “DEBE0EEF2A779A4CAAC54EA51B9ACCDED506DA2A4BEBA88FA23AD8E7399C4A8B93A006ACC1D7FEAEE56A5571B5AB6D74819CFADB522FEEB101B4D0F97F4E91” decryptionKey = “7B1EF067E9C561EC2F4695578295EDD5EC454F0F61DBFDDADC2900B01A53D4” 验证= “SHA1” 解密= “AES”/>

  2. 第二种方法是通过 appPool 使用 AspNet_RegIIS 和开关 -ga 为工作进程授予对 HKCU 注册表的访问权限,或者使用 -i 为所有应用程序授予访问权限

aspnet_regiis -ga "IIS APPPOOL\app-pool-name"

无论您选择哪种方法都应该可以解决此问题,但在我看来,未来迁移和服务器更改最可靠的方法将是 web.config 中的唯一键,请记住这将导致应用程序覆盖 HKCU 注册表蜂巢并保持您的应用程序运行。

于 2016-04-22T08:32:45.023 回答
1

我只是有一个类似的问题。我有:

The required anti-forgery form field "__RequestVerificationToken" is not present. 

有趣的是我尝试调试它并在我希望在控制器中找到它的两个地方都看到了令牌

var formField = HttpContext.Request.Params["__RequestVerificationToken"];
var cookie = System.Web.HttpContext.Current.Request.Cookies["__RequestVerificationToken"].Value;

实际上,我应该一直在这里寻找:

var formField = HttpContext.Request.Form["__RequestVerificationToken"];

由于 Params 不仅仅包含表单字段,它还包含 QueryString、Form、Cookie 和 ServerVariables。

一旦那条红鲱鱼消失了,我发现 AntiForgeryToken 的形式有误!

于 2018-06-01T12:52:26.217 回答
-2

html 错误记录器不是正确的行。

您必须检查页面中的所有加载值不为空。

于 2017-05-16T06:30:08.323 回答