6

寻找某人来证实或反驳我的理论,即部署两个 iframe 指向同一域上的两个不同的有状态页面会导致 JSESSIONID 被覆盖。这就是我的意思:

设置

  1. 假设您有两个页面需要 HttpSession 状态(会话亲和性)才能正常运行 - 部署在http://www.foo.com/ page1http://www.foo.com/ page2
  2. 假设 www.foo.com 是运行 Tomcat(6.0.20,fwiw)的单个主机,该主机使用 JSESSIONID 作为会话 ID。
  3. 假设这些页面变成了两个 iframe 小部件嵌入到第 3 方网站:http://www.site.com/page1" />(和 /page2 分别)
  4. 假设有一个第三方网站希望将两个小部件放在同一页面上http://wwwbar.com /foowidgets.html

是否会发生以下竞态条件?

  1. 一位新访客访问http://www.bar.com/foowidgets.html
  2. 浏览器开始加载 foowidgets.html 中的 URL,包括两个 iframe 'src' URL
  3. 因为浏览器针对同一主机打开多个并发连接(在 chrome/ff 情况下最多 6 个),浏览器碰巧同时发出对http://www.foo.com/page1http://www.foo.com的请求/第2页
  4. tomcat@foo.com 几乎同时接收到这两个请求,第一次调用 getSession()(在两个不同的线程上)并懒惰地创建两个 HttpSession,因此,两个 JSESSIONID 的值分别为 $Page1 和 $Page2。这些请求还将数据填充到相应的会话中(处理后续请求需要这些数据)
  5. 假设浏览器首先收到对 page1 请求的响应。浏览器为 HOST www.foo.com 设置 cookie JSESSIONID=$Page1
  6. 收到对 page2 请求的下一个响应,浏览 器用 $Page2覆盖 HOST www.foo.com 的 cookie JSESSIONID
  7. 用户点击 foowidgets.html 上“page1”iframe 中的某些内容;浏览器向http://www.foo.com/page1?action=doSomethingStateful发出第二个请求 。该请求带有 JSESSIONID=$Page2 (而不是 $Page1 - 因为 cookie 值被覆盖)
  8. 当 foo.com 收到此请求时,它会查找错误的 HttpSession 实例(因为 JSESSIONID 键是 $Page2 而不是 $Page1)。富吧!

上述情况会发生吗?我想是的,但希望得到确认。

如果上述显然是可能的,考虑到我们希望每页支持多个 iframe,有哪些解决方案?我们并不迫切需要 iframe 共享相同的 HttpSession,尽管这样会很好。如果解决方案仍会为每个 iframe 规定一个单独的 HttpSession,那么 iframe 1 最终不会引用 iframe 2 的 httpSession 状态而不是自己的状态是强制性的。

在我的脑海中,我能想到:

  1. 将 page1 和 page2 映射到不同的域(操作开销)
  2. 使用 URL 重写,从不使用 cookie(搞乱分析)
  3. 还要别的吗?

非常感谢,-尼基塔

4

3 回答 3

1

TL;DR场景是正确的,一个会话覆盖另一个会话,两个页面共享会话;但没关系。


在上面的示例中,您有两个近乎同时的无状态匿名请求。

换句话说,这个请求绝对没有什么独特之处;将返回两个通用页面。这两个页面都会有新的 JSESSIONID,不是因为比赛,而是因为请求本身是匿名的,因此本质上是要求 Tomcat 创建新会话。

让我们假设 page2 赢得了 JSESSIONID 速度竞赛,并且浏览器现在拥有 page2 cookie。然后用户点击 page1 中的一个动作。我认为您的请求将带有 page2 cookie 标记是正确的。

但那又怎样?

Page1 中不能有任何与会话相关的信息,因此没有用户特定的信息。因此,来自它的操作可以没有与会话相关的状态(状态刚刚创建)。如果没有特定的会话相关状态,那么“错误”JSESSIONID 就没有问题。

换个角度看:如果page2的请求在page1的请求之前已经被完全处理过了,那么page1会有什么不同呢?我看不出有什么不同。如果两种情况下返回的 HTML 没有差异,则交换其 JSESSIONID 无关紧要。

OTOH,如果用户已经访问过 bar.com,那么对 page1 和 page2 的请求将与相同的 JSESSIONID 相关联,返回的页面是正确的,并且在 foo.com 的世界中一切都很好。

一个问题:如果您打开了CSRF保护。CSRF 库修改返回页面中的所有 URL 以包含一个额外的参数。CSRF 保护库检查所有传入请求,确保其安全令牌与 JSESSIONID 匹配。如果 page1 使用 page2 的 cookie,CSRF 保护将拒绝该请求为伪造的。

如果每个 iframe 必须有一个会话:使用 URL 重写。这最初是为在浏览器不接受 cookie 时管理会话而设计的。它运行良好,但 URL 看起来很糟糕。

于 2013-04-24T06:19:23.030 回答
0

如果 page1 和 page2 使用不同的上下文,它们都将通过第三方 iframe 工作,而不会相互干扰。

在 JSP 中有多种控制会话的方法。这个问题的最佳答案可能会帮助您找出正确的解决方案: 在什么条件下创建 JSESSIONID?

于 2011-09-14T09:17:49.060 回答
0

您所说的是正确的,这就是 HttpServletResponse.encodeURL() 方法存在的理由。

如果包含两个 iframe 的页面与 page1 和 page2 处于相同的上下文中,则 iframe 中的 URL 应使用此方法编码或使用 JSTL 的 <c:url> 标签获取。

如果还没有定义 cookie,它将在 URL 中添加 JSESSIONID。

于 2010-03-22T12:44:38.917 回答