Anti Forgery Token竞赛条件

时间:2017-06-28 20:26:04

标签: c# asp.net-mvc iframe cookies

我有一个应该是iFramed的MVC视图。它的几个实例可能是iFramed在同一个主页中。在我看来,我有这个:

@Html.AntiForgeryToken()

我用它来确保调用web api只来自此页面。我的主页可能如下所示:

<iframe src="http://myserver.com/myview?someparameters=0000"></iframe>
<iframe src="http://myserver.com/myview?someparameters=0001"></iframe>
<iframe src="http://myserver.com/myview?someparameters=0002"></iframe>

在我看来,我抓住了令牌并将其提交到标题中,以便我可以在我的API中查看它:

var headers = actionContext.Request.Headers;
var headerToken = headers.Contains("__RequestVerificationToken") ? headers.GetValues("__RequestVerificationToken").FirstOrDefault() : null;
var cookie = headers.GetCookies("__RequestVerificationToken").FirstOrDefault()?["__RequestVerificationToken"]?.Value;

AntiForgery.Validate(cookie,headerToken);

我遇到的问题是,在我的主机页面中,所有三个视图都是并行加载的。因此,他们都在隐藏字段中获取自己的随机令牌并尝试设置cookie。但是,虽然可以有三个独立的独立隐藏输入令牌,但只能有一个cookie。因此,在三个请求中,两个将失败,一个将成功。重新加载页面将使这三个页面再次起作用,大概是因为它们在此时都获得了相同的防伪标记(因为它属于会话 - 如果我理解正确的话)。

那我怎么能避免这个呢?我如何确保他们都获得相同的令牌?

2 个答案:

答案 0 :(得分:0)

您需要在iFrame之外创建AntiForgeryToken,并以某种方式将其传递到子页面。

在您的外部页面中,将防伪令牌作为查询参数传递给子页面

@{    
  var aft = @Html.AntiForgeryToken; 
}
<iframe src="http://myserver.com/myview?someparameters=0000&aft=@aft"></iframe>
<iframe src="http://myserver.com/myview?someparameters=0001&aft=@aft"></iframe>
<iframe src="http://myserver.com/myview?someparameters=0002&aft=@aft"></iframe>

然后,在呈现子视图的页面上,检查是否设置了AFT,如果已设置,请使用@Html.AntiForgeryToken()

答案 1 :(得分:0)

尝试使用partialview。在每个局部视图中,您都可以使用iFrame,所有局部视图都将添加到具有Html.AntiForgeryToken()的主.cshtml文件中。

@Html.AntiForgeryToken()

<div>    
    @{Html.RenderPartial("_iFrame1");}
</ div>
<div>    
    @{Html.RenderPartial("_iFrame2");}
</ div>
<div>    
<div>
@{Html.RenderPartial("_iFrame3");}
</ div>