我们承认这一点 — 我们对会话状态这一概念是如此习以为常,以至于我们忘记了会话状态是在 1997 年用 Active Server Pages (ASP) 引入的一个手段。会话状态使开发人员能够在用户与应用程序交互这段时间内持久保存有关该用户的一块信息。特定于用户的信息通常会保留 20 分钟长的时段,而每当用户返回该站点时,该时段都将重新开始计时。
当用户首次连接到站点时,将以内存块的形式创建一个全新的会话状态以存放数据,同时,还会创建一个 ID 以便将其与当前用户唯一地联系起来。当下一次发出请求时,该用户将被要求提交该会话 ID,以便检索并正确地还原会话状态。会话 ID 是 ASP 和 ASP.NET 完全自主生成的字母数字字符串。用户如何管理它并确保用每个后续请求来包装它呢?
当每个请求到达 IIS 入口时(远远早于它被移交给 ASP.NET),aspnet_filter.dll 获得了一个查看它的机会。如果该 URL 将会话 ID 嵌入到括号中,则会提取该会话 ID 并将其复制到一个名为 AspFilterSessionId 的请求标头中。然后,重写该 URL 以使其看起来像原来请求的资源,并且将其释放。这一次,ASP.NET 会话状态模块从请求标头中检索会话 ID,并且通过会话-状态绑定继续工作。
只要该 URL 包含可用来获取会话 ID 的信息,无 Cookie 机制就可以很好地工作。正如您稍后将看到的那样,这会造成一些使用限制。
让我们研究一下无 Cookie 会话的优缺点。
返回页首 优点 在 ASP.NET 中,会话管理和表单身份验证是唯一的两个在后台使用 Cookie 的系统功能。通过无 Cookie 会话,您现在可以部署无论用户的有关 Cookie 的首选项如何都能正常工作的有状态应用程序。然而,就 ASP.NET 1.x 而言,仍然需要使用 Cookie 来实现表单身份验证。好消息是,在 ASP.NET 2.0 中,表单身份验证可以选择以无 Cookie 方式工作。
另一个经常提出的反对 Cookie 的理由是安全性。这是一个值得予以更多关注的要点。
Cookies 是无活动能力的文本文件,因此,这些文件可能被攻击者替换或损坏 — 只要他们获得了对计算机的访问。真正的威胁并不在于 Cookie 可以在客户端计算机上安装什么,而是在于它们可以向目标站点上载什么。Cookie 不是程序,并且永远不会像程序那样运行;然而,您计算机上安装的其他软件可以使用对 Cookie 的浏览器内置支持来远程从事破坏活动。
此外,Cookie 要受到被盗窃的风险。一旦失窃,包含有价值的和私人的信息的 Cookie 就可能将其内容泄露给恶意攻击者,并且为其他类型的 Web 攻击提供便利。总之,通过使用 Cookie,您将自己暴露在本可以消除的风险之中。这是真的吗?
返回页首 缺点 让我们从另一个角度来考察安全性。您是否曾经听说过会话劫持?如果没有,则请阅读一下 TechNet Magazine 文章 Theft On The Web: Prevent Session Hijacking。简单说来,当攻击者获得对特定用户的会话状态的访问时,将发生会话劫持。其实质是,攻击者窃取有效的会话 ID,并且使用它侵入系统和窥探数据。获取有效会话 ID 的一种常见方式是窃取有效的会话 Cookie。鉴于此,如果您认为无 Cookie 会话保护了您应用程序的安全,那您就完全错了。实际上,对于无 Cookie 会话,会话 ID 直接显示在地址栏中!请尝试下列操作:
1. 连接到使用无 Cookie 会话的 Web 站点(例如,MapPoint)并获得一个映射。此时,该地址存储在会话状态中。
2. 抓取 URL(直至页名称)。不要包括查询字符串,但请确保该 URL 包括会话 ID。
3. 将该 URL 保存到文件中,并将该文件复制/发送到另一台计算机。
4. 在第二台计算机上打开该文件,并将该 URL 粘贴到新浏览器实例中。
5. 只要会话超时仍然有效,就会显示同一个映射。
通过无 Cookie 会话,可以比以往任何时候都更加容易地窃取会话 ID。
从道德的观点来看,窃取会话是应该受到谴责的操作,我相信大家会一致认同这一点。但它是否也是有害的?这取决于会话状态中实际存储的内容。窃取会话 ID 本身并不会执行超出代码控制范围的操作。但是,它可能向未经授权的用户泄露私有数据,并且使一些坏家伙能够执行未经授权的操作。有关如何在 ASP.NET 应用程序中阻止会话劫持的提示,请阅读 Wicked Code: Foiling Session Hijacking Attempts。(而且,它并不依赖于无 Cookie 会话!)
使用无 Cookie 会话还会引起与链接有关的问题。例如,您不能在 ASP.NET 页中具有绝对的、完全限定的链接。如果您这样做,那么源自该超链接的每个请求都将被视为新会话的一部分。无 Cookie 会话要求您总是使用相对 URL,就像在 ASP.NET 回发中一样。仅当您可以将会话 ID 嵌入到 URL 中时,您才可以使用完全限定的 URL。但是,既然会话 ID 是在运行时生成的,那么您如何才能做到这一点呢?
返回页首 小结 ASP.NET 中存在无 Cookie 会话的主要原因是用户(无论出于什么原因)可能在他们的浏览器中禁用了 Cookie。如果您的应用程序需要会话状态,那么无论您是否喜欢,您都必须面对这种情况。无 Cookie 会话将会话 ID 嵌入到 URL 中,并且得到了双重结果。一方面,它们为 Web 站点提供了一种正确标识发出请求的用户的方式。然而,另一方面,它们使会话 ID 清楚地显现在潜在的攻击者面前,从而使攻击者可以轻松地窃取它并以您的身份进行操作。
Dino Esposito 是 Wintellect 的讲师和顾问,他居住在意大利。他是 Programming Microsoft ASP.NET 以及更新的 Introducing Microsoft ASP.NET .0(两者都由 Microsoft Press 出版)的作者,他的大多数时间都用来讲授有关 ASP.NET 和 ADO.NET 的课程以及在会议上发表讲演。请在 http://weblogs.asp.net/despos 浏览 Dino 的网络日记。