未提供所需的防伪令牌或无效

时间:2011-12-21 13:58:59

标签: c# asp.net-mvc model-view-controller antiforgerytoken

我正在使用MVC 3,从我能看到的一切设置正确。

用户身份验证使用AntiForgery令牌提交表单,一切正常。

除非用户已将表单保留为打开并且在该时间内用户登录已过期,否则

当用户提交表单时,由于他们不再经过身份验证,他们应该被带回登录页面。 (这确实发生了一些次)

取而代之的是“未提供所需的防伪令牌或无效”。被扔了。我想它会被抛出,因为加密的令牌包含一些用户细节,由于用户不再经过身份验证而无法验证这些细节。

异常是正确的但是永远不应该抛出,因为页面应该跳回登录屏幕,因为真正的问题是用户离开了打开的表单并且他的登录超时了。

这个问题难以复制,因为它并不总是这样做。

我看到很多人似乎遇到了这个问题,但没有解决方案。

这是MVC本身的问题吗?

机器密钥设置和内容都是正确的,所以这不是问题。

3 个答案:

答案 0 :(得分:5)

这样做的原因似乎是,在某些大型组织中,人们在没有重新启动的情况下打开机器并打开浏览器而不会在很长时间内关闭它们。有时甚至几周。

如果稍后添加了机器密钥或更改了机器密钥,则尚未关闭或关闭浏览器的机器会导致此错误。重新启动每台计算机或关闭浏览器后,错误将停止。

注意:要停止此错误,创建计算机密钥也很重要。

Google:机器密钥生成器

答案 1 :(得分:3)

我在这里添加了一个更好的答案,因为这是一个非常痛苦的问题并且在整个网络上都没有得到很好的回答我认为我会添加我当前正在使用的解决方案。

从根本上(忽略各种选项)AntiForgeryToken通过添加会话cookie来工作,然后在通过使用[ValidateAntiForgeryToken]属性装饰控制器来发布表单时读取该会话cookie。

首先,在我们作为一般规则修改任何内容之前,请始终执行以下操作。

  1. 在web.config中创建一个machineKey,如下所示。

    <machineKey validationKey="YOUR_KEY" decryptionKey="YOUR_KEY" validation="SHA1" decryption="AES" />

    **注意SHA1这不再是非常安全了,但这是另一个讨论**

    Google <machineKey> Generator并配置。

    http://msdn.microsoft.com/en-us/library/w8h3skw9%28v=vs.100%29.aspx

  2. 从&#39; __ RequestVerificationToken&#39;更改默认Cookie名称一个会 不被其他应用程序使用。 (我总是使用GUID)。

    使用AntiForgeryConfig.CookieName = "YOUR_NAME";

  3. 执行此操作
  4. 创建新的自定义属性。

  5. 此错误似乎无缘无故地出现的原因是cookie仅在会话期间有效。出于各种原因,但大多数情况下,人们在非常非常非常长的时间内打开页面会超时。由于会话超时,因此cookie不再有效。

    另一个问题是,如果您在发布到控制器上有[Authorize]属性,那么事物流将在检查HttpAntiForgeryException以查看谁进行身份验证之前触发。 (在会话过期的大多数基于cookie的身份验证中,用户不再进行身份验证)

    解决此问题的方法是创建自定义[CustomValidateAntiForgeryToken]属性。

    [AttributeUsage( AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true )]
      public class CustomValidateAntiForgeryToken : FilterAttribute, IAuthorizationFilter {
    
        public void OnAuthorization( AuthorizationContext filterContext ) {
    
          if ( filterContext == null ) {
            throw new ArgumentNullException( "filterContext" );
          }
    
          try {
            AntiForgery.Validate();
          }
          catch {
    
            // Here do whatever is you wish 
            // you could just re throw the error or what ever.
    
            // In this case I have redirected to a Signout
    
            filterContext.Result = new RedirectToRouteResult( 
              new RouteValueDictionary( 
                new {
                  action     = "Sign_Out",
                  controller = "SOME_CONTROLLER",
                  area       = ""
                } 
              )
            );
    
          }
    
        }
    
      }
    

    最后,如果你在任何现有的系统中更改任何一个,请确保每个人都注销,关闭他们的浏览器甚至重新启动,如果可能的话,清除他们的cookie和缓存。在更改代码后,即使您已为每个用户完成此操作,您仍可能会收到错误。

    显然人们有不同的需求,但希望这给出了足够的建议来控制这个非常普遍和恼人的问题。

    如果有人看到任何有用或可以添加的内容,请执行。

答案 2 :(得分:1)

在您的操作上,将[Authorize]属性置于[ValidateAntiForgeryToken]属性之上。它们从上到下按顺序执行。因此,它应该达到授权,并且看到您不再经过身份验证。