Asp.net mvc 4 具体来说,AntiForgeryToken是如何与#x27;匹配';用饼干?

Asp.net mvc 4 具体来说,AntiForgeryToken是如何与#x27;匹配';用饼干?,asp.net-mvc-4,cookies,http-post,verification,antiforgerytoken,Asp.net Mvc 4,Cookies,Http Post,Verification,Antiforgerytoken,我们有一个网页,上面有一个表单。有一个antiforgerytoken通过帮助程序添加到此MVC页面的表单中: @Html.AntiForgeryToken() 我们今天意识到我们缓存了页面,我们认为这将是一个巨大的问题,但是多台机器可能会提交相同的表单,即使它们在页面的源代码中共享相同的验证令牌 据我所知,这是出乎意料的,我以为这个想法是在cookie中可以找到相同的验证令牌?我显然误解了令牌背后的机制(包括页面和用户cookie的修改) 有人能给我解释一下这个页面是如何工作的吗?更具体地说

我们有一个网页,上面有一个表单。有一个antiforgerytoken通过帮助程序添加到此MVC页面的表单中:

@Html.AntiForgeryToken()
我们今天意识到我们缓存了页面,我们认为这将是一个巨大的问题,但是多台机器可能会提交相同的表单,即使它们在页面的源代码中共享相同的验证令牌

据我所知,这是出乎意料的,我以为这个想法是在cookie中可以找到相同的验证令牌?我显然误解了令牌背后的机制(包括页面和用户cookie的修改)

有人能给我解释一下这个页面是如何工作的吗?更具体地说,服务器是如何验证表单的post请求的

我认为这就像服务器检查令牌字符串是否与cookie中的令牌字符串相同一样简单

注意:缓存现在已经关闭了fwiw,我们对缓存一个带有令牌的页面并不100%满意,因为我们对它的了解有点多了

我们今天意识到我们缓存了页面,我们认为这将是一个巨大的问题,但是多台机器可能会提交相同的表单,即使它们在页面的源代码中共享相同的验证令牌

是的,当涉及到防伪令牌时,缓存是一个问题。你有两个选择:

  • 不要缓存表单
  • 使用
    OutputCache
    VaryByCustom
    属性根据令牌本身的不同而变化
  • 我手头没有代码,所以我将向您展示一个取自本文的示例:

    为了避免此问题,可以在OutputCache属性上使用VaryByCustom属性:

    [OutputCache(
      Location = OutputCacheLocation.ServerAndClient,
      Duration = 600,
      VaryByParam = "none",
      VaryByCustom = "RequestVerificationTokenCookie")]
    public ActionResult Index()
    {
      return new View();
    }
    
    然后在global.asax的GetVaryByCustomString方法上编程规则:

    public override string GetVaryByCustomString(HttpContext context, string custom)
    {
      if (custom.Equals("RequestVerificationTokenCookie", StringComparison.OrdinalIgnoreCase))
      {
        string verificationTokenCookieName =
          context.Request.Cookies
            .Cast<string>()
            .FirstOrDefault(cn => cn.StartsWith("__requestverificationtoken", StringComparison.InvariantCultureIgnoreCase));
        if (!string.IsNullOrEmpty(verificationTokenCookieName))
        {
          return context.Request.Cookies[verificationTokenCookieName].Value;
        }
      }
      return base.GetVaryByCustomString(context, custom);
    }
    
    public重写字符串GetVaryByCustomString(HttpContext上下文,字符串自定义)
    {
    if(custom.Equals(“RequestVerificationTokenCookie”,StringComparison.OrdinalIgnoreCase))
    {
    字符串验证KenCookieName=
    context.Request.Cookies
    .Cast()
    .FirstOrDefault(cn=>cn.StartsWith(“\uu requestverificationtoken”,StringComparison.InvariantCultureInogoreCase));
    如果(!string.IsNullOrEmpty(verificationTokenCookieName))
    {
    返回context.Request.Cookies[verificationTokenCookieName].Value;
    }
    }
    return base.GetVaryByCustomString(上下文,自定义);
    }
    
    按评论编辑
    它之所以能工作是因为它只是将cookie的值与表单上生成的隐藏字段的值进行比较。服务器上没有维护的令牌列表,如果您认为它可能是这样工作的,那么就可以进行验证。这意味着,就客户端而言,尽管在服务器上缓存了表单的生成,但客户端仍然会收到一个“新”表单,并因此收到一个cookie,因此比较不会失败。

    您的意思是希望发布缓存的表单失败,但它会起作用吗?抱歉@CodeCaster,我肯定说得不够清楚。是的,我希望缓存的表单失败。但它是有效的。它不应该起作用,如何使用自定义过滤器或通过其他方式禁用cacahing已经在很多问题中得到了回答(只需搜索“mvc antiforgerytoken缓存”)。我认为OP的问题在于它确实有效,尽管每个人都说它不应该有效。@CodeCaster啊,我当时可能误解了这个问题。我将把这个放在这里,看看他在删除之前先回答了什么。对不起,约翰,我可能不够清楚+1不管怎样,非常感谢您的努力。@JayMee无需道歉。CodeCaster发现了这一点,所以我认为这只是因为我周末的大脑没有发挥作用@约翰-我明白了(我想)。因此,当服务器为同一表单提供服务时(即,缓存表单中隐藏有其他人的令牌),服务器也会将第二个用户的cooke设置为该“共享令牌”值?所以所有用户都将拥有相同的令牌,但这很好——因为所有用户都将拥有相同的令牌值写入他们的cookie?如果是这样的话,为什么缓存是件坏事?再次感谢,感谢这是周末,应该是人们的休息时间。