【问题标题】:A required anti-forgery token was not supplied or was invalid所需的防伪令牌未提供或无效
【发布时间】:2012-01-25 07:56:52
【问题描述】:

我正在使用 MVC 3,从我所见,一切都已正确设置。

用户 Authenticates 使用 AntiForgery 令牌提交表单,一切正常。

除非用户将要提交的表单保持打开状态并且在该时间内用户登录已过期。

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

而是出现异常“未提供所需的防伪令牌或该令牌无效。”被抛出。我想它被抛出是因为加密的令牌包含一些无法验证的用户详细信息,因为用户不再经过身份验证。

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

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

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

这是 MVC 本身的问题吗?

机器键设置和东西都是正确的,所以不是问题。

【问题讨论】:

  • 防伪功能实际上发生在System.Web.WebPages,而不是 MVC。因此,您需要查看该源代码,而不是 MVC。
  • 我不确定 AntiForgeryToken 与用户有什么关系,因为无论授权如何,它都可以使用。这可能与时间有关。

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


【解决方案1】:

我在这里添加了一个更好的答案,因为这太痛苦了,而且整个网络上的答案都很糟糕,我想我会添加我目前工作的解决方案。

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

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

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

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

    ** 注意 SHA1 这已经不是很安全了,但那是另一个讨论 **

    Google &lt;machineKey&gt; Generator 并配置。

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

  2. 将默认 cookie 名称从“__RequestVerificationToken”更改为 不被其他应用程序使用。 (我总是使用 GUID)。

    使用AntiForgeryConfig.CookieName = "YOUR_NAME"; 执行此操作

  3. 创建一个新的自定义属性。

此错误似乎无缘无故出现的原因是 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】:

    原因似乎是在某些大型组织中,人们在很长一段时间内让他们的机器打开而不重新启动,并且浏览器打开而不关闭它们。有时甚至连续数周。

    如果机器密钥是在以后添加或更改的,则未关闭或关闭浏览器的机器是导致此错误的机器。一旦每台机器重新启动或浏览器关闭,错误就会停止。

    注意:要阻止此错误,创建机器密钥也很重要。

    谷歌:机器密钥生成器

    【讨论】:

    • 我不知道为什么这被否决了。这正是导致我们出现问题的原因,一旦添加了机器密钥并重新启动了所有机器,问题就不再发生了。
    【解决方案3】:

    在您的操作上,将[Authorize] 属性放在[ValidateAntiForgeryToken] 属性上方。他们从上到下按顺序执行。所以,它应该点击授权,然后看到您不再经过身份验证。

    【讨论】:

    • 属性不能保证按照你写它们的顺序被检索,是吗?
    • Ryand.Johnson 已经是这种情况了,尽管这不应该真正导致问题
    猜你喜欢
    • 1970-01-01
    • 2012-06-09
    • 2013-01-27
    • 1970-01-01
    • 2014-03-07
    • 2013-05-25
    • 2011-02-16
    • 2012-02-19
    相关资源
    最近更新 更多