解决防伪令牌问题

Jer*_*ose 34 asp.net-mvc antiforgerytoken asp.net-mvc-3

我有一个表格帖子,一直给我一个反伪造令牌错误.

这是我的表格:

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

这是我的行动方法:

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

这是web.config中的machineKey:

<system.web>
  <machineKey validationKey="mykey" decryptionKey="myotherkey" validation="SHA1" decryption="AES" />
</system.web>
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误:

A required anti-forgery token was not supplied or was invalid.
Run Code Online (Sandbox Code Playgroud)

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

[HttpGet]
public ActionResult Join()
{
    return this.View();
}
Run Code Online (Sandbox Code Playgroud)

所以我不确定发生了什么.我一直在搜索,似乎所有东西都表明它是机器键更改(应用程序周期)或用户/会话更改.

还有什么可以继续?我该如何解决这个问题?

Sim*_*ver 31

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

等等......

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

提供的防伪令牌适用于用户"",但当前用户为"XXX@yahoo.com".

(现在我将假设在MVC4中更改了这个确切的错误消息,并且这与您获得的消息基本相同).

那里有很多人仍然双击一切 - 这很糟糕! 刚刚醒来之后我才想到这一点,所以这是如何通过测试我真的不知道.您甚至不必双击 - 如果按钮没有响应,我第二次点击时自己就会出现此错误.

我刚刚删除了验证属性.我的网站始终是SSL,我并不过分关注风险.我现在需要它才能工作.另一种解决方案是使用javascript禁用按钮.

这可以在MVC4初始安装模板上重复.

  • 我使用这段代码来防止这类问题$('#loginForm form').submit(function(){$(this).find('input [type = submit]').attr("disabled","disabled" );}); (3认同)

Jer*_*ose 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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

我的问题是它将Identity用户名与表单令牌的用户名进行比较的情况.在我的情况下,我没有设置用户名(一个是null,另一个是空字符串).

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


Vah*_*idN 9

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

  • 这不是我的解决方案...我尝试过,但是没有用 (4认同)

Boh*_*ets 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();
});
Run Code Online (Sandbox Code Playgroud)

要么

$('#loginForm').submit(function () {
    $(this).find(':submit').attr('disabled', 'disabled'); 
});
Run Code Online (Sandbox Code Playgroud)