我有一个 flex/LCDS 堆栈,我发现在注销后,我经常(但不总是)开始Duplicate HTTP Session
在客户端收到错误。
这是堆栈的重要事实:
- flex 客户端在应用程序中具有登录/注销功能。退出后页面不刷新。(因此,Flex 应用程序和底层
mx.messaging.FlexClient
保持初始化) - 用户可能打开了多个选项卡。
per-client-authentication
设置为false
- 我们正在尝试实现 SSO(与 CAS 集成),因此用户原则绑定到 JSession。- 当使用长轮询进行消息传递以及打开两个(或更多)选项卡时,问题最为明显。
- 使用 RTMP 或 Streaming 频道时,该问题很难重现。
- 用户绑定到 JSession - 即,如果他们在 Tab1 上登录,他们将在 Tab2 上登录。
- 当用户从任一选项卡注销时,Jsession 将失效。
这是我目前关于导致问题的原因的理论:
- Tab1 (T1) 启动客户端 -> Issued ClientId1 (C1) -> JSession1 (J1) created
- Tab2 (T2) 启动客户端 -> 发布 ClientId2 (C2) -> 加入 J1
- T1 登录 -> J1 不受影响
- T2 登录 -> J1 不受影响
- T1 & T2 都订阅,开始轮询
amflongpolling
- T1 发送注销 -> J1 无效 -> J2 创建
- T2 发送轮询(针对 J1)
- T1 注销完成,返回 J2,更新 cookie
最后两个调用产生冲突,LCDS 认为这FlexClient
似乎与 2 个 JSession 相关。
结果,收到如下错误:
Server.Processing.DuplicateSessionDetected 检测到重复的基于 HTTP 的 FlexSession,通常是由于远程主机禁用会话 cookie。必须启用会话 cookie 才能正确管理客户端连接。
注意:我已经能够在独立项目中重现该问题。 我相信这不是我们的应用程序特定代码的问题,而是由状态/会话性质和共享同一会话的多个选项卡之间的冲突引起的。
总之,我认为问题是由于来自一个选项卡的调用而导致服务器上的会话无效,但是在将响应发送到浏览器以通知它新的 JSession 之前,调用是在旧的 JSession 下发出的.
有哪些适当的策略可以防止这种重复会话问题?
更新
澄清一下,虽然场景与此处讨论的场景相似,但存在细微的差异,导致该文章中的解决方案不合适。
具体来说,本文讨论了通过使用 JSP 或协调的 RemoteObject 调用控制跨两个浏览器的 JSession的初始创建来防止重复会话。
Flex 实际上通过阻止出站 RemoteObject 调用来协助这个过程,直到DSid
定义了本地 FlexClient 变量,表明初始会话已经建立。
我的情况不同,因为 JSession (和相关的 LCDS FlexSession / 客户端 FlexClient 对象)已经建立了一次,(使用该文章中讨论的技术)并随后通过注销无效 - 这调用session.invalidate()
- 销毁 JSession。
当 Tab2 发送一个带有陈旧 JSession 的调用时,就会出现问题,这是一个重复的 HTTP 会话错误。然后情况变得复杂,当 LCDS 抛出 DuplicateHTTPSession 错误时,它也会使与客户端连接的所有已知 Jsession 无效,这意味着 Tab1(本来没问题的)现在有一个陈旧的 JSession。下次 Tab1 发送调用时,IT 会导致 DuplicateHTTPSession 错误,并且循环重复。
不幸的是,用于在会话建立时延迟调用的 Flex 框架挂钩没有简单的方法(我发现)一旦设置就可以重新启用。(我尝试了以下方法,但无济于事:)
// Reset DSid to get a new FlexSession established on LCDS
use namespace mx_internal
public function resetFlexSession()
{
FlexClient.getInstance().id = null;
// Note - using FlexClient.NULL_ID also doesn't work.
}