【问题标题】:Anti Forgery Token race conditionAnti Forgery Token 竞争条件
【发布时间】:2017-12-02 09:03:14
【问题描述】:

我有一个应该是 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。所以在这三个请求中,两个会失败,一个会成功。重新加载页面将使所有三个再次工作,大概是因为此时它们都获得了相同的防伪令牌(因为它属于会话 - 如果我理解正确的话)。

那么我该如何避免这种情况呢?如何确保他们都获得相同的令牌?

【问题讨论】:

  • 您可以通过不使用 iframe 来避免这种情况。所以问题是:你能改变设计吗?你需要 iframe 吗?每个 iframe 是否都包含一个表单?因为防伪令牌只会用于发布信息。
  • @RuardvanElburg - 不是真的。这个想法是,这是一个小部件类型的东西,我们的客户可以放到他们自己的页面上。问题是他们想在同一个页面上放置几个,周围有自己的内容。 iframed 页面本身必须进行一些后端调用,这些调用通过检查令牌来保护,但也许我必须重新考虑这一点。
  • 还有一个 javascript 解决方案?
  • @HoomanBahreini - 令牌不是问题。 Cookie 是。
  • @HoomanBahreini - 这是一个仅限 http 的 cookie。无法从 javascript 访问它。此外,检查它是否已经设置仍然会导致完全相同的竞争条件。事实上,这正是@Html.AntiForgeryToken() 内部发生的事情。它检查是否已经设置了 cookie,如果没有,则创建一个新的并在 html 中创建一个隐藏的 input 标记。问题是两个请求同时进来,而且都没有cookie。

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


【解决方案1】:

您需要在 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()

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2018-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多