36

如果答案是肯定的,那么 ASP.NET MVC 将如何找出哪个令牌链接到哪个表单以及如何验证它?

我已经看到它为每个表单创建了两个单独的标记。

4

2 回答 2

34

在这种情况下,您无需执行任何特定操作。ASP.NET MVC 将简单地为所有表单重用相同的值,因此它不需要知道哪个表单发送了请求来验证它。只需Html.AntiForgeryToken()在每个表单中添加一个并使用该属性装饰您发布到的每个控制器操作[ValidateAntiForgeryToken],您应该就可以了。

于 2011-05-04T19:54:39.140 回答
11

这里有一篇很棒的文章, 我指出了一些重要的部分。

简而言之,如果可以从请求的 cookie 集合中反序列化令牌,它将重用该令牌而不是生成新令牌。如果 cookie 集合中不存在令牌,它将实例化一个新的“AntiForgeryToken”实例并随机生成一个新的 16 字节数组来表示该令牌。

public AntiForgeryToken GetCookieToken(HttpContextBase httpContext)
{
    HttpCookie cookie = httpContext.Request.Cookies[this._config.CookieName];

    if (cookie == null || string.IsNullOrEmpty(cookie.Value))
        return (AntiForgeryToken) null;

    return this._serializer.Deserialize(cookie.Value);
}

在生成第一个令牌并将其保存到 cookie 集合后,对辅助方法“Html.AntiForgeryToken()”的所有后续调用将遵循相同的步骤并重用 cookie 集合中的现有令牌,而不是生成新值。

由于它是一个会话 cookie,这意味着防伪令牌的值仅在浏览器会话期间生成一次,并在所有后续调用中重复使用。

那么,如果它们重用相同的标记,为什么隐藏字段值会彼此不同呢?

因此,虽然加密的值可能看起来不同,但解密的值是相同的。

byte[] one = MachineKey45CryptoSystem.Instance.Unprotect("iAdQj5D0qrMuTggD8WpnOZPlVOfHg_qmPIEjnULAYd1h56cV2cL51rcaY8_UgxQbav5_6KTAtyE52ir1X6GmaS9ZPgw1");
byte[] two  = MachineKey45CryptoSystem.Instance.Unprotect("Shvi8Bxe6-a8zfCfDGnxkaC-IETsbjkR9iIylwn-2VRWQ-GtQkdowdFw1biU7dN3j-xPJZHYQPe-hNfWspYjy_ZcCCY1");
byte[] three = MachineKey45CryptoSystem.Instance.Unprotect("ZhaVFngUMLo88jmTIx___BTWlYFyKh1GalwEeffRl0-o3Gu7_m98k6aQjO7IysZIdXxVx6TqL6QIfX19Uwq3Ia6dghA1");

比较所有三个字节数组表明它们是相同的。

于 2018-08-27T14:06:12.797 回答