5

我有一个 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.
   }
4

3 回答 3

1

我对你有感觉 - 我已经为此奋斗了很长时间,但从未找到解决方案,但找到了一个对我有用的解决方案,所以希望它至少可以控制这个问题,直到你找到罪魁祸首。(如果您这样做,请在此处发布)。

现在,我的环境与您略有不同(我在后端使用 CF),所以请记住这一点。

我还尝试了整个“FlexClient.getInstance().id = null;” 事情也是如此,它本身并不能工作,但正是我实现它的方式地点使它工作。

所以,这就是所做的,让问题消失了。

在我的主窗体上,在进行任何RemoteServer 调用之前,我设置了一个 creationComplete 处理程序并放置了您已经知道并喜欢的代码:

// Not sure if this is needed anymore, but I'm leaving it in
FlexClient.getInstance().id = null;

接下来,在我第一次调用服务器时,我优雅地处理了故障,并再次清除了那个臭名昭著的 ID:

    public function login(event:Event): void {

        Swiz.executeServiceCall(roUsers.login(),
            function (event:ResultEvent): void {
                // Handle a successful login here...
            }
            , function (faultevent:FaultEvent): void {
                // This code fixes this issue with IE tabs dying and leaving Flex with a Duplicate Session problem.
                if (faultevent.fault.faultString.indexOf("duplicate")) {
                  FlexClient.getInstance().id = null;
                  Swiz.dispatchEvent(event);
                }
        });

    }

奏效了。

基本上,尝试呼叫,如果重复会话失败,则清除该 ID 并重新发出呼叫。

关键是我认为在您至少调用一次服务器之前清除 ID 是有效的。一旦你这样做了,它对我来说就像一个魅力,在我所有的应用程序中。

请注意,我使用的是上面的 SWIZ 框架,所以只需将其转换为您自己的世界。

顺便说一句,我在除 IE 之外的任何其他浏览器中从未见过此错误,我相信这可能与 IE 所遭受的臭名昭著的死标签问题有关。

如果上述方法不起作用,我还知道对服务器上某些配置文件的一些更改可能会有所帮助。

祝你好运,我的朋友!

于 2011-11-22T23:50:05.610 回答
0

这篇题为“避免 LCDS 中检测到重复会话的错误”的文章深入解释了您的情况。这是一个相关的报价:

...[LCDS] 认为它收到请求的 FlexClient 已经与服务器上的不同会话相关联。

为了让客户端应用程序确保应用程序中的 FlexClients 不会进入这种不良状态,客户端应用程序必须确保在多个 FlexClients 同时连接到服务器之前已经在服务器上建立了会话。

有几种方法可以解决这个问题,包括:

  • 调用jsp页面加载应用
    "The jsp page could both create a session for the client application and return an html wrapper to the client which would load the swf."
  • 呼叫远程目的地
    "which would automatically create a session for the client application on the server"
于 2011-11-21T18:25:37.600 回答
0

一个额外的、不相关的、需要注意的原因;

某些浏览器(例如 Internet Explorer)将域命名规则应用于 cookie,这意味着像“my_clientX.server.com”这样的代码域虽然可能返回有效的 BlazeDS 响应,但会在访问 cookie 时不断触发重复的会话通知将被阻止。

将名称更改为有效名称(不带下划线)将解决问题。

于 2014-09-02T13:51:04.487 回答