为什么@ Html.AntiForgeryToken()在同一响应中生成不同的标记?

5 security asp.net-mvc antiforgerytoken razor asp.net-mvc-4

单个Razor视图包含多个表单,每个表单都有自己的调用 @Html.AntiForgeryToken()

<form id="f1">
    @Html.AntiForgeryToken()
</form>

<form id="f2">
    @Html.AntiForgeryToken()
</form>
Run Code Online (Sandbox Code Playgroud)

据我了解,这两种防伪代币应该是相同的.

<form id="f1">
    <input name="__RequestVerificationToken" type="hidden" value="duVT4VtiYybun-61lnSY1ol__qBwawnELooyqT5OSrCJrvcHvDs_Nr9GLxNxwvBaI4hUcKZVkm6mDEmH2UqNorHD1FnJbKJQLWe8Su_dhy_nnGGl5GhqqC3yRGzcxbBM0" />
</form>

<form id="f2">
    <input name="__RequestVerificationToken" type="hidden" value="ZMISz3IWHU_HCKP4FppDQ5lvzoYhlQGhN1cmzKBPz4OgDzyqSUK3Q1dqvw1uHsb4eNyd9U3AbFcnW8tR7g1QS8Dyhp0tFc-ee1sfDAOqbLCcgd3PDnLCbXx09pnPREaq0" />
</form>
Run Code Online (Sandbox Code Playgroud)

为什么价值不同?

当然它们应该是相同的,因为它们是从服务器发送的相同响应中的?
文件没有提到只有一次调用它.

vto*_*ola 10

我担心这不起作用.

防伪令牌也会在响应cookie中传播,因此您的只会包含最后一个令牌,因此第一个表单将始终失败.

您可以尝试执行以下操作:

@{
    ViewBag.Title = "Index";
    var token = Html.AntiForgeryToken();
}

<form id="f1">
    @token 
</form>

<form id="f2">
    @token 
</form>
Run Code Online (Sandbox Code Playgroud)

我试过了,两种形式都使用相同的标记.

  • 您的方法会产生安全漏洞,如下面提供的答案中所述.您不应对页面中存在的每个表单使用相同的标记. (3认同)
  • 没错.制作此帮助程序的开发人员决定每次调用生成一次.这就是API.这是开发人员的决定(可能很多人都在考虑).如果您喜欢您描述的行为,请自行实施 - 这就是编程的美妙之处! (2认同)

Dan*_*yak 2

防伪令牌不会直接比较 - 服务器必须首先取消对其的保护并比较内部受保护的数据。拥有不同的受保护令牌并不一定意味着它们包含不同的数据。

比较的System.Web.Helpers.AntiXsrf.TokenValidatorSecurityToken解密AntiForgeryToken实例的内部。然而,这些实例还包含一个AdditionalData字段、一个UserName字段和一个ClaimUid字段。

另外,SecurityToken里面的内容AntiForgeryToken是直接从里面的AntiForgery cookie(如果有效的话是当前的,否则是新生成的)复制的AntiForgeryWorker

鉴于所有数据都经过序列化、加密然后编码,由于AdditionalData令牌之间的差异,受保护的令牌可能会存在差异,或者可能是由于加密过程中使用的伪随机数(它可能使用它,因为我可以测试 2 个完全不同的令牌对于同一个 cookie 是否有效)。