液晶显示器与Flex - 防止注销后出现 DuplicateHTTPSession 错误

发布于 2024-12-16 20:14:55 字数 2588 浏览 2 评论 0原文

我有一个 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) Starts client ->已发出 ClientId1 (C1) -> JSession1 (J1) 创建
  • 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 调用来协助此过程,直到定义本地 FlexClient DSid 变量(表明初始会话已建立)为止。

我的场景有所不同,因为 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.
   }

I have a flex/LCDS stack, where I'm finding that after logout, I often (but not always) start receiving Duplicate HTTP Session errors on the client.

Here's the important facts of the stack:

  • The flex client has a login/logout functionality within the app. The page does not refresh after the logout. (Therefore, the Flex app, and the underlying mx.messaging.FlexClient remains initialised)
  • A user may have multiple tabs open.
  • per-client-authentication is set to false - we're trying to achieve SSO (integrating with CAS) so the user principle is bound to the JSession.
  • The problem is most evident when using long-polling for messaging, and when there are two (or more) tabs open.
  • The problem is very difficult to reproduce when using RTMP or Streaming channels.
  • A user is bound to a JSession - ie., if they log in on Tab1, they become logged in on Tab2.
  • When a user logs out from either tab, the Jsession is invalidated.

Here's my current theory as to what's causing the issue:

  • Tab1 (T1) Starts client -> Issued ClientId1 (C1) -> JSession1 (J1) created
  • Tab2 (T2) Starts Client -> Issued ClientId2 (C2) -> Joins J1
  • T1 logs in -> J1 Unaffected
  • T2 logs in -> J1 Unaffected
  • T1 & T2 Both subscribe, start polling over amflongpolling
  • T1 sends logout -> J1 Invalidated -> J2 created
  • T2 sends poll (against J1)
  • T1 logout completes, returns with J2, updates cookie

The last two calls create a conflict, where the LCDS sees the FlexClient appears to be related to 2 JSessions.

As a result, an error along the lines of the following is recieved:

Server.Processing.DuplicateSessionDetected Detected duplicate
HTTP-based FlexSessions, generally due to the remote host disabling
session cookies. Session cookies must be enabled to manage the client
connection correctly.

Note: I've been able to recreate the problem in a stand-alone project. I believe it's not an issue with our application specific code, instead caused by the Stateful / session nature and conflicts between multiple tabs sharing the same session.

In summary, I believe the issue is caused where the session is invalidated on the server as a result of calls from one tab, but before the response is sent to the browser to inform it of the new JSession, calls are issued under the old Jsession.

What are some appropriate strategies to defend against this duplicate session issue?


Update

To clarify, while the scenario is similar to those discussed here, there are subtle differences which make the solutions in that article inappropriate.

Specifically, the article discusses preventing duplicate sessions by controlling the initial creation of JSessions across both browsers, using a JSP, or an orchestrated RemoteObject call.

Flex actually assists in this process by preventing outbound RemoteObject calls until the local FlexClient DSid variable is defined, showing that the initial session has been established.

My scenario differs, because the JSession (& associated LCDS FlexSession / Client-Side FlexClient objects) have already been established once, (using the techniques discussed in that article) and subsequently invalidated via logout - which calls session.invalidate() - destroying the JSession.

The issue arises when Tab2 sends a call with a stale JSession, a duplicate HTTP Session error. The situation then gets compounded, as when LCDS throw the DuplicateHTTPSession error, it also invalidates all known Jsessions attached with the client, meaning that the Tab1 - which had been ok - now has a stale JSession. The next time that Tab1 sends a call, IT causes a DuplicateHTTPSession error, and the cycle repeats.

Unfortunately, the Flex framework hooks for delaying calls while sesssions are established have no easy way (that I've found) of being re-enabled once set. (I've tried the following, to no avail:)

 // 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.
   }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

如此安好 2024-12-23 20:14:55

我同情你 - 我已经与这个问题斗争了很长时间,从未找到解决方案,但找到了一个对我有用的解决方案,所以希望它至少能控制这个问题,直到你找到解决方案罪魁祸首。 (如果您这样做,请将其发布在这里)。

现在,我的环境与您略有不同(我在后端使用 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 所遭受的臭名昭著的死标签问题有关。

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

祝你好运,我的朋友!

I feel for you - I've fought this for a long time and never found a solution, but found a fix that worked for me so hopefully it will at least keep this issue under control until you can find the culprit. (And if you do, please post it here).

Now, I've got a slightly different environment than you (I'm using CF on the backend) so keep that in mind.

I also tried the whole "FlexClient.getInstance().id = null;" thing too and it didn't work by itself, but it was how and where I implemented it that made it work.

So, this is what I did that made the problem go away.

On my main form, before ANY RemoteServer calls are made, I setup a creationComplete handler and placed this code you already know and love:

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

Next, in my very first call to the server, I gracefully handle the failure, and clear that stinking ID out again:

    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);
                }
        });

    }

And it worked.

Basically, try the call, and if it fails for the duplicate session thing, then clear out that ID and reissue the call.

The key point being that I don't think clearing out the ID works until you've made at least one call to the server. Once you do, it worked like a CHARM for me, and in all of my apps.

Note that I'm using the SWIZ framework above so just translate it to your own world.

By the way, I've never seen this error in any other browser but IE, and I believe it may have something to do with the infamous Dead Tab Issue that IE suffers from.

If the above doesn't work, I also know of a few changes to some config files on the server that might help.

Good luck my friend!

生死何惧 2024-12-23 20:14:55

本文标题为避免重复会话检测到 LCDS 中的错误,深入解释了您的情况所发生的情况。这是一个相关的引用:

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

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

建议采用多种方法来解决此问题,包括:

  • 调用 jsp 页面来加载应用程序
    “jsp 页面既可以为客户端应用程序创建会话,又可以将 html 包装返回给客户端,以加载 swf。”
  • 调用远程处理目标
    “这将自动为服务器上的客户端应用程序创建会话”

This article titled, Avoiding duplicate session detected errors in LCDS, gives an in-depth explanation of what's happening in your situation. Here is a relevant quote:

...[LCDS] believes that the FlexClient it received the request from was already
associated with a different session on the server.

For the client application to make sure that FlexClients in the
application don’t get into this bad state, the client application must
make sure that a session is already established on the server before
multiple FlexClients connect to the server at the same time.

There are several approaches recommended to fixing this, including:

  • calling a jsp page to load the application
    "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."
  • calling a Remoting destination
    "which would automatically create a session for the client application on the server"
夏日浅笑〃 2024-12-23 20:14:55

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

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

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

An additional, unrelated, cause to be aware of;

Some browsers (Internet Explorer, for example) apply domain naming rules to cookies and this means that a code domain like "my_clientX.server.com", although it may return valid BlazeDS responses, will continually trigger duplicate session notifications as access to the cookie will be blocked.

Changing the name to a valid name (without underscore) will resolve the issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文