【问题标题】:Should the SessionID in the QueryString or the Cookie of a GET request take precedence?QueryString 中的 SessionID 还是 GET 请求的 Cookie 是否应该优先?
【发布时间】:2011-07-25 11:10:58
【问题描述】:

如果我收到对 url host.com/site-directory/page-slug.html?session={someValidNonExpiredSessionGuid} 的请求,并且我检测到会话 cookie 的值是:{someOtherValidNonExpiredSessionGuid},那么

哪个会话是与请求关联的正确会话?

这里有一些背景:

我用于跨 HTTP 请求维护状态的模式是在查询字符串、表单集合和/或 cookie 中存储唯一 ID。然后,在每个请求中,我都会找到唯一的 ID 并从数据库表中提取日期。如果 id 无效,或者会话过期,将创建一个新会话(使用新 id、新 cookie 等)。

默认行为是所有表单都有一个字段:

 <input type="hidden" name="session" value="{someGuid}" />

网站上其他页面的所有链接都将附加一个查询字符串参数

 <a href="site-directory/page-slug.html?session={someGuid}">a sample link</a>

而且,如果用户的浏览设备支持 cookie,则会设置一个具有会话值的 cookie。

如果我已验证用户的浏览设备支持 cookie,那么我的表单和查询字符串将不再需要会话 ID 字段/参数。

但是,在决定查询字符串的会话参数是否应优先于 cookie 值或反之亦然时,我遇到了一个概念性问题。似乎在任何一种情况下我都可能获得不良数据。如果用户使用 URL 中包含的会话参数为页面添加书签,我可以获得带有错误查询字符串参数的数据。如果用户在没有终止会话的情况下关闭浏览器,并且会话过期窗口尚未关闭,我也可能从 cookie 中获取错误数据。似乎这两个选项都容易受到恶意用户拦截请求并发送具有相同会话信息的请求的攻击。

所以,再一次,我的问题是

如果我收到对 url host.com/site-directory/page-slug.html?session={someValidNonExpiredSessionGuid} 的请求,并且我检测到会话 cookie 的值为:{someOtherValidNonExpiredSessionGuid},那么 哪个会话是与请求关联的正确会话?

我倾向于使用 cookie 会话,因为似乎最常见的场景是包含会话的书签。我已经决定表单发布数据应该具有最大的优先级,因为页面总是会使用正确的 ID 呈现表单,而唯一可能出现错误、未过期 ID 的情况是非常快速实施的 XSS 攻击,这可以通过包含请求范围的防伪令牌字段来规避。

除了主要问题之外,我感谢我在此描述中表达的任何与安全相关或逻辑疏忽的见解。我为这篇长篇博文道歉,但觉得有必要解释一下情况。非常感谢您的意见。

此外,它不一定与问题相关,但我在大多数情况下使用 ASP.NET MVC,并使用 Response.Cookies 手动设置我的 cookie。

【问题讨论】:

  • 我很困惑。为什么你意识到这么难的解决方案?您使用什么会话状态存储:inproce、memcache、db 或其他?
  • @Antony Blazer,使用 ASP.NET 的 SessionState 是一个实现细节。我的问题是概念性的,适用于任何 HTTP 应用程序。

标签: asp.net-mvc http session security httprequest


【解决方案1】:

从安全角度来看,会话不应存储在查询字符串中。

例如: 如果会话存储在查询中,并且您链接到同一页面上的远程主机,则用户的有效会话可以通过引用标头发送到远程主机。

会话应始终存储在 cookie 中。

【讨论】:

  • 在浏览器不支持 cookie 或关闭 cookie 的情况下,您关于“会话应始终存储在 cookie 中”的论点似乎存在很大问题。
【解决方案2】:

您应该尝试将其存储在 cookie 中(查看浏览器上限以查看浏览器是否支持 cookie),然后回退查询字符串。

【讨论】:

    【解决方案3】:

    如果出现歧义,我也倾向于使用 cookie 会话 ID。这主要是因为我相信 cookie 实现比我自己的自制会话跟踪实现更完善、更经过测试和更防白痴。例如在某些情况下,ASP.NET 会自动知道清除会话 cookie、更新它们等。

    另外,我会设计它,使 cookie 不会持久化,以尽量减少边缘情况。如果用户关闭浏览器,则会话关闭。

    我会考虑的另一个简化是使用基于 cookie 或基于 URL 的跟踪,而不是两者兼而有之。如果浏览器支持 cookie,那么确实没有理由也通过 URL 跟踪会话。

    想法?

    很好奇...您排除使用库存 ASP.NET 无 cookie 会话实现的原因是什么? - http://msdn.microsoft.com/en-us/library/aa479314.aspx#cookieless_topic2

    【讨论】:

    • 因为并非所有环境都支持 ASP.NET 生命周期。今天我在使用 ASP.NET MVC,但明天我可能无法访问它,所以我想了解基础知识。
    • 另外,您的简化问题出在第一个请求中。在您尝试在一个请求上设置 cookie 并在后续请求中检索之前,您无法确定浏览器是否正确支持 cookie。因此,在验证之前呈现的任何链接都需要在 url 中包含会话。
    • 是的。我已经看到实现尝试在用户第一次访问站点时设置带有 HTTP 重定向的 cookie,以查看 cookie 是否返回。我可以用这种方法想到一些极端情况,但总的来说 - 据我回忆 - 它工作可靠。
    【解决方案4】:

    如果我收到对 url 的请求 host.com/site-directory/page-slug.html?session={someValidNonExpiredSessionGuid} 我检测到一个会话cookie 价值: {someOtherValidNonExpiredSessionGuid}, 那么哪个会话是正确的 与请求关联的会话?

    要回答您的具体问题,我建议将会话管理放在 cookie 中,而不是在查询字符串中。如前所述,cookie 可以设置为过期,而查询字符串则不能。这允许您的瘦客户端通过删除他们自己的过期 cookie 来协助他们自己的会话维护。此外,由于 cookie 被丢弃到特定浏览器,因此您可以减少其他浏览器欺骗原始浏览器会话的机会。

    我使用查询字符串传递会话信息的唯一方法是作为一种备份方法,在新浏览器实例上重新建立浏览器会话。这是一个场景:您在机器 A 上使用浏览器 A 进行了活动会话,该会话遇到了一些灾难性错误。您想要一种在同一台机器或另一台机器上的另一个浏览器实例上重新建立相同会话的方法。如果您的代码隐藏可以识别会话 cookie 不存在,但查询字符串中存在有效的会话 id,您可以发起质询-响应以验证该会话 id 的完整性并然后在新机器上放置一个新的会话 cookie。在我看来有点极端,但该功能在某些情况下可能很有用。

    添加:我知道您可能希望容纳已在浏览器上关闭 cookie 的用户,而您可以使用查询字符串来保存我不推荐的会话 ID。但是,如果必须,请使用浏览器机器特定信息加密该傻瓜。

    【讨论】:

      猜你喜欢
      • 2023-03-07
      • 2019-08-23
      • 2015-07-01
      • 1970-01-01
      • 2016-09-16
      • 1970-01-01
      • 2016-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多