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 tofalse
- 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.
}
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:
There are several approaches recommended to fixing this, including:
"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"