如果我在一个页面中添加多个表单,是否需要在每个表单中添加单独的防伪标记?

时间:2011-05-04 18:13:59

标签: asp.net-mvc antiforgerytoken

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

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

2 个答案:

答案 0 :(得分:26)

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

答案 1 :(得分:3)

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

简而言之, 如果可以从请求的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");

比较所有三个字节数组可以发现它们是相同的。