The ADEP Post is a human-moderated aggregator of the best user assistance content created by the LiveCycle/Adobe Digital Enterprise Platform community. The community at large includes partners, users, customers, and Adobe professionals.
This blog aggregates content relevant to both the LiveCycle Enterprise Suite as well as the recently-released Adobe Digital Enterprise Platform.

Setting up an LCDS Edge server can sometimes seem a bit daunting but there really isn’t all that much to it

To illustrate this point, I’ll show you how to setup the lcds-samples web application from one LCDS 3.1 turnkey installation to act as the Edge server to another lcds-samples web application from a second LCDS 3.1 turnkey installation. The great thing about this example is that you won’t need to recompile any Flex applications to see this working!

To make things easier you will need two machines. One to run each Tomcat server from the two turnkey installations. I used my laptop and a VMWare instance for this. This is so you don’t need to waste time configuring everything to avoid port conflicts and in the real world the two servers would be on separate machines anyway.

Install LCDS 3.1 on your two test machines now using the installer for your platform. I used Windows.

The setup for the app tier server is the simplest so let’s do that one first. Find the services-config.xml file for the lcds-samples webapp on one machine and open it up for edit. On my app tier machine, I installed LCDS to C:\lcds31_app so my services-config.xml can be found at C:\lcds31_app\tomcat\webapps\lcds-samples\WEB-INF\flex\services-config.xml.

In the channels section add the following channel definition for the gateway endpoint. This is what the Edge server will talk to on the backend.

Um, so that’s it for the app tier. You can start the database server and the Tomcat server on this machine now. We’re also going to use the TraderDesktop sample for this demo so you can go ahead and start the TraderDesktop ticker feed by requesting the following URL in a browser (assuming you’re on the local server).

http://localhost:8400/lcds-samples/traderdesktop/startfeed.jsp.

Now for the Edge server. Find the services-config.xml file for the lcds-samples webapp on your other machine and open it up for edit. On my Edge server machine, I installed LCDS to C:\lcds31_edge so my services-config.xml can be found at C:\lcds31_edge\tomcat\webapps\lcds-samples\WEB-INF\flex\services-config.xml.

There is a bunch of stuff here we don’t need so let’s comment it out. All the destinations we want to talk to are in the app tier so we don’t need any destinations defined at the Edge. We also don’t need any services except the gateway service which we will be adding in a second.

Now add the following gateway service definition to the services section of your services-config replacing your.app.tier.server with the ip address for the machine that is running your app tier server.

Session re-writing is the practice of adding the session identifier to the HTTP request URL instead of passing the session identifier as a session cookie. Session re-writing is usually used when cookies have been disabled on the client. It is an easy way to let clients that do not allow or support cookies maintain session state with the server but it poses some security risks. The session identifier is passed in the URL which means that it is not encrypted even if the request is made over SSL/HTTPS. Because of the security risks associated with session re-writing, the Open Web Application Security Project (OWASP) recommends that session re-writing only be used for low-value sites. In this article, I will show you how to disable session re-writing in BlazeDS and LCDS to help secure your application.

In BlazeDS and LCDS, the session identifier is typically either the JSessionId (for servlet based endpoints in BlazeDS or LCDS) or AMFSessionId (for NIO HTTP based endpoints in LCDS).

Note that the RTMP protocol doesn’t use HTTP, so the issue of session re-writing doesn’t apply to RTMP endpoints.

When the BlazeDS or LCDS server receives a request with no session identifier (either a session cookie or session id URL parameter) a couple things happen. A new session is created. A Set-Cookie header with the session id is added to the response. Also, an AppendToGatewayURL header with the session id is added to the AMF or AMFX response message.

The BlazeDS/LCDS client code looks for the AppendToGatewayURL header and will grab the AMFSessionId or JSessionId from the header. The client code will then add the session id as a URL parameter to every request made to the server. Here is what the request URL with the session id in URL parameter looks like.

If cookies are supported by the browser, the browser will also send a session cookie with the session id with every request. If both a session cookie and session id URL parameter are found, the application server will typically use the session cookie and ignore the URL parameter.

The way that session re-writing is currently implemented in BlazeDS and LCDS is not ideal because the session id url parameter is often sent unnecessarily when the browser does in fact support cookies. This can be mitigated by making sure that an HTTP session already exists before a request is made to the BlazeDS/LCDS server. In that case, the server would not add the AppendToGatewayURL header to the AMF/AMFX response message and no session id URL parameter would be sent by the client.

Note that one way to do this would be to make the main page for the application be a jsp page that would create the HTTP session then return the BlazeDS/LCDS application SWF to the client.

This will make it so the client won’t send the session id in a URL parameter if cookies are enabled but what OWASP recommends is that this functionality be disabled altogether. Usually, app servers provide a switch do disable session re-writing. In BlazeDS/LCDS, there is no switch to disable this feature but luckily it is fairly easy to disable session re-writing on your own. This can be done by writing a custom channel.

The process for disabling session re-writing is slightly different for AMF and AMFX channels.

Note that the channels that use the AMFX message format in BlazeDS and LCDS are named HTTP, for example HTTPChannel and StreamingHTTPChannel. To avoid confusing the HTTP in the channel name with the HTTP protocol, I refer to these channels as AMFX channels.

To disable session re-writing for one of the AMF channels, you just need to extend the channel and override the AppendToGatewayUrl function. Here is an example of a custom channel that extends AMFChannel to disable session re-writing.

To disable session re-writing for one of the AMFX channels, you just need to extend the channel and override the appendToURL setter. Since the setter is marked mx_internal you also need to make sure your custom class imports and uses the mx_internal namespace. Here is an example of a custom channel that extends HTTPChannel to disable session re-writing.

To use the custom channel in your application all you need to do is create a ChannelSet that contains the custom channel and assign the ChannelSet to your BlazeDS/LCDS component (Producer, Consumer, DataService, etc.). Here is a code snippet that shows how to do this for Producer and Consumer components.

Keep in mind that for any channel you create manually (rather than retrieving it from the ServerConfig), you need to set the endpoint URL yourself as well as any channel specific properties such as the polling interval.

I hope this article will help you make your BlazeDS/LCDS applications more secure. For more security best practices around session management, I recommend reading this OWASP session management guide.

When debugging BlazeDS/LCDS customer issues it’s often helpful to have a capture log of the traffic sent between the client and the server. Because the traffic is usually binary AMF and not plain text a tool that can decode AMF messages must be used.

I usually recommend a popular commercial HTTP debugger that has AMF support for this, but sometimes customers are reluctant to buy it especially if they are not used to doing this type of testing and may not need such a tool again.

For these customers and anyone else who would like a free alternative, I recently discovered the HTTP/HTTPS debugging utility WebScarab which is a project maintained by OWASP.

I was able to get WebScarab up and running pretty quickly. While the commercial tool I typically use automatically configures the proxy settings for the browser to route traffic through the tool, I had to set this up myself for WebScarab. After I did this though, I was able to easily view and modify AMF messages sent between the client and the server.

Saving snapshots and opening them up again for viewing was pretty easy as well. Each snapshot doesn’t get saved as a single file but rather as a bunch of files in a directory, so you will likely need to zip this up if you want to send it to someone to look at.

All in all, WebScarab seems to be an impressive little utility. I think I’ll definitely be using it more in the future. . . especially as people start sending me capture logs in the WebScarab format. . .

There are a number of situations where you might have more than one FlexClient in a LCDS application. For example, if you loaded two LCDS apps into a parent application as sub apps, each LCDS app would have its own FlexClient.

Note: The FlexClient represents the LCDS application on the server.

For the LCDS sub apps to work correctly they must each be able to maintain session with the server. LCDS runs in a JEE application container and leverages this container for things like security (authentication/authorization) and session handling. Currently the client application is responsible for ensuring that each FlexClient can maintain session with the server. Failing to do this will result in duplicate session detected errors like the following.

In our example of two LCDS sub apps running in a parent application, if both sub apps load at the same time and simultaneously make requests to the server without a session already established on the server for the client application here is what happens. . . The server will receive ping requests from both sub apps. Neither ping request will have a session cookie header as there is no session cookie currently stored for the client application by the browser (or AIR runtime). The server will create a new session for each request and also create FlexClients for each request and tie these FlexClients to their respective sessions.

Note: The client ping requests will have a DSID of nil which tells the server that a new FlexClient needs to be created.

The replies for each of these requests will be returned to the client. When the browser (or other client runtime such as AIR) receives the first response it will store the session cookie set by the set cookie header.

Note: If one of the HTTP endpoints is being used, the session cookie is the standard JSESSIONID cookie used by JEE application containers. If one of the NIO HTTP endpoints is being used, this by default is the AMFSessionID cookie. The session cookie name for NIO HTTP endpoints can be changed in your services-config.xml file.

When the browser receives the second response, it will overwrite the first session cookie with the new session cookie on this response. Both session cookies have the same path element so only one will get stored by the browser. Each sub app will store the DSID (the FlexClient id) included in the reply message it received from the server.

The client is now in a bad state because on the server the first FlexClient is associated with a session that the browser no longer knows about. If the first FlexClient makes another request to the server, the request will have the session cookie header for the second FlexClient and the server will throw a duplicate session detected error. This is because it correctly 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 a number of ways you could implement this. If a browser is being used to run the application and not AIR, you could call 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. If the application will be run in AIR as well, the parent application could call a jsp page or servlet that would create a session for the client application and then the parent application could load the sub apps. The parent application could also call a Remoting destination which would automatically create a session for the client application on the server but would also create an additional FlexClient which you may not want.

It would be nice if there was a way to resolve this in LCDS and not make application developers have to think about it. The flexibility of LCDS makes it difficult to provide a solution that works for everyone though. LCDS sub apps loaded with SWFLoader run independently of each other. To make this work LCDS would have to provide its own components for loading and managing sub apps which definitely seems like overkill. Neither JEE nor most browsers appear to provide a clean way to have more than one session per client application. For the NIO HTTP endpoints where we provide our own session implementation, it may be possible to implement a solution where the session cookie name would be unique for each FlexClient. Rather than using a common session cookie name such as AMFSESSIONID, we could possibly make the session cookie name a combination of the common name and a unique identifier such as the session id or FlexClient id which would prevent the browser from overwriting these cookies if the path element on the set cookie header was the same. For now though, you’ll have to use one of the workarounds I’ve suggested or come up with your own. Just make sure that all FlexClient instances in your application share a single session on the server.