我有一个flex/lcd堆栈,我发现注销后,我经常(但并不总是)开始在客户端接收Duplicate HTTP Session
错误。
下面是关于栈的一些重要事实:
- flex客户端在应用程序中有一个登录/注销功能。注销后页面不会刷新。(因此,Flex应用程序和底层
mx.messaging.FlexClient
保持初始化) - 用户可以同时打开多个选项卡。
-
per-client-authentication
设置为false
-我们试图实现SSO(与CAS集成),因此用户原则绑定到JSession。 - 在使用长轮询进行消息传递时,以及打开两个(或更多)选项卡时,问题最为明显。 当使用RTMP或流媒体通道时,这个问题很难重现。
- 用户绑定到一个JSession。,如果他们登录了Tab1,他们也会登录Tab2。
- 当用户从任意一个选项卡注销时,Jsession失效。
以下是我目前关于导致问题的原因的理论:
- Tab1 (T1) start client -> Issued ClientId1 (C1) -> JSession1 (J1) created
- Tab2 (T2) start Client -> Issued ClientId2 (C2) -> Joins J1
- T1登录-> J1未受影响
- T2登录-> J1未受影响
- T1,T2都订阅,开始在
amflongpolling
上轮询 - T1发送注销-> J1无效-> J2创建
- T2发送轮询(对J1)
- T1注销完成,返回J2,更新cookie
最后两个调用创建了一个冲突,其中lcd看到FlexClient
似乎与2个JSessions相关。
结果,接收到如下一行的错误:
Server.Processing。DuplicateSessionDetected检测到的副本基于http的FlexSessions,通常是由于远程主机禁用会话cookie。必须启用会话cookie才能管理客户端正确连接。
注意:我已经能够在一个独立的项目中重新创建这个问题。我相信这不是我们应用程序特定代码的问题,而是由有状态/会话性质和共享同一会话的多个选项卡之间的冲突引起的。
总之,我认为这个问题是由于一个选项卡调用导致会话在服务器上无效,但是在将响应发送到浏览器以通知它新的JSession之前,调用是在旧的JSession下发出的。
有什么合适的策略来防御这个重复的会话问题?更新
需要澄清的是,虽然场景与本文讨论的相似,但存在一些微妙的差异,这些差异使得文章中的解决方案不合适。
具体地说,本文讨论了通过使用JSP或编排的RemoteObject调用控制跨两个浏览器的JSessions的初始创建来防止重复会话。
Flex实际上通过阻止出站RemoteObject调用来帮助这个过程,直到定义了本地FlexClient DSid
变量,表明初始会话已经建立。
我的场景不同,因为JSession (&关联的LCDS FlexSession/客户端FlexClient对象)已经建立了一次(使用那篇文章中讨论的技术),随后通过注销(调用session.invalidate()
)使其失效,从而破坏JSession。
当Tab2发送一个带有失效JSession(一个重复的HTTP Session错误)的调用时,问题就出现了。然后,情况变得更加复杂,因为当lcd抛出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.
}
我为你感到-我已经为此奋斗了很长时间,从未找到解决方案,但找到了一个修复,为我工作所以希望它至少会控制这个问题,直到你能找到罪魁祸首。(如果有的话,请贴在这里)。
现在,我的环境与您略有不同(我在后端使用CF),所以请记住这一点。
我也尝试了整个"FlexClient.getInstance()"。id = null;" thing too 本身不起作用,但是how和where我实现了它,使它起作用
所以,这就是我所做的使问题解决了。
在我的主表单上,在任何 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所遭受的臭名昭著的死Tab问题有关。如果上面的不起作用,我也知道对服务器上的一些配置文件进行一些更改可能会有所帮助。
祝我的朋友好运!这篇题为"避免lcd中重复会话检测到的错误"的文章深入解释了在您的情况下发生的情况。这里有一个相关的引用:
有几种方法可以解决这个问题,包括:…[LCDS]认为它收到请求的FlexClient已经存在了与服务器上的另一个会话相关联。
对于客户端应用程序,要确保FlexClients在应用程序不会进入这种糟糕的状态,但客户机应用程序必须这样做确保之前已经在服务器上建立了会话多个flexclient同时连接到服务器。
- 调用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"
需要注意的另一个不相关的原因;
一些浏览器(例如Internet Explorer)对cookie应用域名命名规则,这意味着像"my_clientX.server.com"这样的代码域,尽管它可能返回有效的BlazeDS响应,但会不断触发重复的会话通知,因为对cookie的访问将被阻止。
将名称更改为有效名称(不带下划线)将解决此问题。