为什么/何时会话写入容易受到线程终止?

时间:2010-02-15 17:45:29

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

代码:

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

问题:

当foo.aspx从会话中读取“foo”时,它不在那里。 会话就在那里,但“foo”没有价值。

我在生产环境中间歇地观察到了这一点。但我不是要问a question about Response.Redirect()

说明:

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

  

现在,重定向的作用是发送一个   对客户端的特殊标题   它要求服务器有所不同   页面比它等待的页面。   服务器端,发送后   header,Redirect结束响应。   这是一件非常暴力的事情。   Response.End实际上停止了   在任何地方执行页面   使用ThreadAbortException。什么   真的发生在这里是   会话令牌在战斗中丢失

我的看法是,Response.Redirect()可能会因为结束线程而变得严厉。如果它们发生得太接近那种笨拙的话,这可能会威胁到我的会话写入。

问题:

ASP.NET会话管理如何让它容易受到攻击?在会话写入行“完成”之前,Response.Redirect()代码行不会开始执行 - 如何对会话写入构成这样的威胁?

在下一行代码执行之前,会话写入没有“完成”怎么办?是否存在会话写入类似(就好像它们从未发生过)丢失的其他场景?

3 个答案:

答案 0 :(得分:2)

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

在任何情况下,Response.Redirect()都有一个重载,它带有一个布尔参数,允许您指定是否要结束线程。

Response.Redirect(string url,  bool endResponse);

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

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

答案 1 :(得分:1)

在测试了几个替代方案(Response.Redirect(...,false),Server.Transfer()以及我现在无法回忆的其他“解决方案”之后,我们发现这个问题只有一个可靠的答案。

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

答案 2 :(得分:0)

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