AntiForgeryToken,具体来说,'match up' 如何使用 cookie?
How does AntiForgeryToken, specifically, 'match up' with a cookie?
我们有一个网页,上面有一个表格。通过帮助程序将防伪令牌添加到此 MVC 页面的表单中:
@Html.AntiForgeryToken()
我们今天意识到我们已经缓存了页面,我们认为这将是一个大问题,但是多台机器可能会提交相同的表单,即使它们在页面源中共享相同的验证令牌!?
据我所知,这是出乎意料的,我的想法是可以在 cookie 中找到相同的验证令牌?我显然误解了令牌背后的机制(在页面上和用户 cookie 的修改)。
有人可以向我解释此页面如何仍然有效吗? 更具体地说,服务器如何验证表单的 post 请求。
我认为这就像服务器检查令牌字符串是否与在 cookie 中找到的令牌字符串相同一样简单。
注意:暂时关闭缓存,我们对缓存带有令牌的页面不是 100% 满意,因为我们对它有了更多了解。
We realised today that we have the page cached, which we thought would be a massive issue, but multiple machines may submit the same form, even though they share the same verification token in the page's source!?
是的,就防伪令牌而言,缓存是一个问题。您有两个选择:
- 不缓存表单。
- 使用
OutputCache
的 VaryByCustom
属性 因令牌本身而异。
我手边没有代码,所以我将向您展示一个摘自 this 文章的示例:
In order to avoid this issue you can use the VaryByCustom property on the OutputCache attribute:
[OutputCache(
Location = OutputCacheLocation.ServerAndClient,
Duration = 600,
VaryByParam = "none",
VaryByCustom = "RequestVerificationTokenCookie")]
public ActionResult Index()
{
return new View();
}
And then program the rule on the global.asax‘s GetVaryByCustomString method:
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);
}
根据评论编辑
它起作用的原因是因为它只是将 cookie 的值与表单上生成的隐藏字段的值进行比较。如果您认为它可能以这种方式工作,则服务器上没有维护的令牌列表可供验证。这意味着,就客户端而言,尽管生成的表单缓存在服务器上,客户端仍会收到 'new' 表单,因此还会收到一个 cookie,因此比较不会失败的。
我们有一个网页,上面有一个表格。通过帮助程序将防伪令牌添加到此 MVC 页面的表单中:
@Html.AntiForgeryToken()
我们今天意识到我们已经缓存了页面,我们认为这将是一个大问题,但是多台机器可能会提交相同的表单,即使它们在页面源中共享相同的验证令牌!?
据我所知,这是出乎意料的,我的想法是可以在 cookie 中找到相同的验证令牌?我显然误解了令牌背后的机制(在页面上和用户 cookie 的修改)。
有人可以向我解释此页面如何仍然有效吗? 更具体地说,服务器如何验证表单的 post 请求。
我认为这就像服务器检查令牌字符串是否与在 cookie 中找到的令牌字符串相同一样简单。
注意:暂时关闭缓存,我们对缓存带有令牌的页面不是 100% 满意,因为我们对它有了更多了解。
We realised today that we have the page cached, which we thought would be a massive issue, but multiple machines may submit the same form, even though they share the same verification token in the page's source!?
是的,就防伪令牌而言,缓存是一个问题。您有两个选择:
- 不缓存表单。
- 使用
OutputCache
的VaryByCustom
属性 因令牌本身而异。
我手边没有代码,所以我将向您展示一个摘自 this 文章的示例:
In order to avoid this issue you can use the VaryByCustom property on the OutputCache attribute:
[OutputCache( Location = OutputCacheLocation.ServerAndClient, Duration = 600, VaryByParam = "none", VaryByCustom = "RequestVerificationTokenCookie")] public ActionResult Index() { return new View(); }
And then program the rule on the global.asax‘s GetVaryByCustomString method:
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); }
根据评论编辑
它起作用的原因是因为它只是将 cookie 的值与表单上生成的隐藏字段的值进行比较。如果您认为它可能以这种方式工作,则服务器上没有维护的令牌列表可供验证。这意味着,就客户端而言,尽管生成的表单缓存在服务器上,客户端仍会收到 'new' 表单,因此还会收到一个 cookie,因此比较不会失败的。