【问题标题】:Why/when are session writes vulnerable to thread termination?为什么/何时会话写入容易受到线程终止的影响?
【发布时间】:2011-01-17 02:11:20
【问题描述】:

代码:

Session["foo"] = "bar";  
Response.Redirect("foo.aspx");

问题:

当 foo.aspx 从会话中读取“foo”时,它并不存在。 session 存在,但“foo”没有任何价值。

我在我们的生产环境中间歇性地观察到了这种情况。但我不是在这里问a question about Response.Redirect()。

解释:

Bertrand Le Roy 解释(粗体字是我的):

现在,重定向所做的是发送一个 客户端的特殊标头,以便 它要求服务器提供不同的 页面比它正在等待的页面。 服务器端,发送后 标头,重定向结束响应。 这是一件非常暴力的事情。 Response.End 实际上停止了 执行页面,无论它在哪里 使用 ThreadAbortException。什么 真正发生在这里的是 会话令牌在战斗中丢失。

我的收获是 Response.Redirect() 可以通过结束线程来处理。如果它们发生得太接近那种严厉,那可能会威胁到我的会话写作。

问题:

ASP.NET 会话管理如何使其如此容易受到攻击? Response.Redirect() 代码行在会话写入行“完成”之前不会开始执行——它怎么会对我的会话写入造成如此大的威胁?

在下一行代码执行之前会话写入没有“完成”怎么办?是否存在其他会话写入同样丢失(好像从未发生过)的情况?

【问题讨论】:

    标签: asp.net session volatile response.redirect risk-analysis


    【解决方案1】:

    我对会话编写的内部结构不够熟悉,但我认为它有一些复杂性,因为它依赖于将浏览器会话 cookie 转换为服务器标识。此外,运行时中的 ThreadAbortExceptions do have special considerations 可能会在这里播放,我不确定。

    无论如何,Response.Redirect() 有一个重载,它接受一个布尔参数,让您指定是否要结束线程。

    Response.Redirect(string url,  bool endResponse);
    

    如果您在 endResponse 设置为“false”的情况下调用它,它将优雅地完成,而不是在内部调用 Thread.Abort()。但是,这意味着它还会在完成之前执行页面生命周期中剩余的任何代码。

    一个好的折衷办法是先调用Response.Redirect(url, false),然后调用Application.CompleteRequest()。这将允许您的重定向发生,但也可以通过最少的额外生命周期处理优雅地关闭当前执行上下文。

    【讨论】:

      【解决方案2】:

      在测试了几种替代方案(Response.Redirect(..., false)、Server.Transfer() 和其他我现在想不起来的“解决方案”)之后,我们只找到了一个可靠的解决方案。

      将我们的会话状态从 InProc 移动到 SqlServer 有效地从我们的系统中消除了这种行为,使 Response.Redirect(...) 完全可靠。如果进一步的测试显示其他情况,我会在这里报告,但我要说的是,为了让这种情况在您的环境中停止发生:将您的会话状态移动到 SqlServer(或者“脱离 InProc”是否足够好?我不确定)。

      【讨论】:

        【解决方案3】:

        应用程序池回收可能会导致您的会话消失。您可以将应用程序池配置为在固定时间回收(推荐,在夜间或在低使用率期间)或增加应用程序池回收的超时期限。

        【讨论】:

          猜你喜欢
          • 2015-12-16
          • 1970-01-01
          • 1970-01-01
          • 2015-04-17
          • 1970-01-01
          • 1970-01-01
          • 2021-07-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多