Asp.net mvc 防伪令牌问题的疑难解答

Asp.net mvc 防伪令牌问题的疑难解答,asp.net-mvc,asp.net-mvc-3,antiforgerytoken,Asp.net Mvc,Asp.net Mvc 3,Antiforgerytoken,我有一个表单帖子,总是给我一个防伪令牌错误 这是我的表格: @using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.EditorFor(m => m.Email) @Html.EditorFor(m => m.Birthday) <p> <input type="submit" id="Go" value="Go" /> </p>

我有一个表单帖子,总是给我一个防伪令牌错误

这是我的表格:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.EditorFor(m => m.Email)
    @Html.EditorFor(m => m.Birthday)
    <p>
        <input type="submit" id="Go" value="Go" />
    </p>
}
以下是web.config中的machineKey:

<system.web>
  <machineKey validationKey="mykey" decryptionKey="myotherkey" validation="SHA1" decryption="AES" />
</system.web>
我已经读到,在HttpContext上更改用户将使令牌无效,但这里没有发生这种情况。HttpGet on my Join操作仅返回以下视图:

[HttpGet]
public ActionResult Join()
{
    return this.View();
}
所以我不确定发生了什么。我到处搜索,似乎所有的东西都表明要么是machineKey在改变(应用程序周期),要么是用户/会话在改变


还可能发生什么?如何对此进行故障排除?

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

在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();
        }
    }
我的问题是,它将身份用户名与表单令牌的用户名进行比较。在我的例子中,我没有设置用户名(一个为null,另一个为空字符串)


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

我刚刚遇到了一个问题,
@Html.AntiForgeryToken()
被调用了两次,因此反伪造令牌在HTTP Post有效负载中出错。

我不知道您的意思是您能够按需获取错误,还是您在日志中看到了错误,但无论如何,这里有一种方法可以保证反伪造令牌错误

等等

  • 确保您已注销,然后输入您的登录名
  • 双击登录按钮
  • 您将获得:
提供的防伪令牌用于用户“”,但当前用户为“XXX@yahoo.com“

(现在,我将假设这个错误消息在MVC4中发生了变化,这与您得到的消息基本相同)

有很多人仍然双击所有东西-这很糟糕我刚醒来就发现了这一点,所以我真的不知道这是如何通过测试的。你甚至不必双击——如果按钮没有响应,我自己在第二次单击时也会出现这个错误

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


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

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

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

$('#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();
});


另一个可能导致我出现此错误的原因是:我的一个表单中有两个
@Html.AntiForgeryToken()


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

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

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

//防止双重表格提交
$('form','loginForm')。提交(函数(){
if($(this).valid()){
$(this.find(':submit').attr('disabled','disabled');
}
});

当我不得不将我的应用程序迁移到一台新机器上时,我也遇到了同样的问题。我不明白为什么会突然出现这个错误,但我确信它与迁移有关,所以我开始调查通过aspnet_reqsql注册数据库的情况,当这被消除后,我意识到这一定与注册应用程序有关,我确信我在类似的地方找到了答案。我在旅途中也发现有两种方法可以解决这个问题

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

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

  • aspnet_regais-ga“IIS应用程序池\应用程序池名称”


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

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


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

    我刚刚遇到了类似的问题。我得到:

    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包含的不仅仅是表单字段,它还包含查询字符串、表单、Cookies和服务器变量


    一旦那条红鲱鱼消失了,我发现防伪代币的形式不对

    我在Mac上的Windows虚拟机上运行这个。但我呆在虚拟世界里。该服务器是由VisualStudio(2010)启动的开发服务器。我还使用主机头记录将“真实”URL路由到我的本地框(即,使实时URL指向我的本地框)。关于马赫数
    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"];