by Steven J. Owens (unless otherwise attributed)
Problem: You have sensitive information on one server that you need to pass to another server without making the user log in twice, or saving the information in a cookie.
Specifically, although you could use a browser session cookie (a cookie with max-age set to -1, which is never written and is discarded when the browser is closed), you can't afford the chance that the user might walk away from the browser while it is still running (e.g. at a public terminal).
Logically, you have three possible solutions.
This involves either cookies, which you usually can't use for security reasons, or an intermediary page with an HTML form and some javascript that submits the form off to server 2. Depending on how tight security is, you might squeak through with the form. The gotcha here will be making sure the form data doesn't get cached.
There are two tricks to use to ensure this. How tricky you have to get depends on what range of browsers you have to support. Different browser versions vary widely in how well they handle caching or not caching pages.
One useful trick to know is that if you use various browser directives to disable caching on the page you return from a form POST, some browsers will helpfully offer to repost the form data to regenerate the page. To avoid this, instead of directly returning the new page, momentarily server-side cache the data and send a browser-side redirect to a second servlet path. The second servlet path then generates the page using the data submitted by the POST, but to the browser it doesn't look like a POST-generated page - so it won't ever offer to rePOST the data.
The second trick is that, not all browsers will properly respect the cache-disabling directives. Therefore, you need to also make sure that if that form ever gets displayed again, the data is no longer in the form. You do this by including a bit of extra javascript in the page to clear the form after you submit it the first time. You can either do this after you do the form.submit, or you can have some sort of onLoad that gets triggered when the page gets redisplayed.
Yet another trick is to use a self-closing pop-up window that submits the POST while targeting it back at the primary window. You still need to use the redirect trick, but by closing the window after sending the POST, you eliminate any possiblity of the user getting back that page.
Compared to all of the above machinations, this might actually be the easiest approach. Essentially you have server 1 act as a proxy server for the initial connection and login to server 2, then redirect the client over to server 2.
You just use the java.net.HttpURLConnection from server 1 to post the session details over to server 2, and create a similar session object over there, get the session cookie back from server 2, send it back to the user's browser as a cookie, and then redirect the user over to server 2.
The only tricky bit is cookie namespace. Each cookie can have a domain defined for it. On any future requests to that domain, the browser automatically includes the cookie with the request. If both servers have the same root domain, you can use that root domain for the cookie's domain and the browser will hand it over to either server.
Having said that, it is therefore probably a bad idea to actually use the JSESSION name for the session cookie that the J2EE spec (I think) defines for the session keys. If you do, you'll have confusion between the two app servers over which session the cookie refers to. Therefore, from server 1, set a temporary cookie containing the value, and have the redirect point to a location on server 2 that sets up a normal session cookie. The only information you actually pass around is the session cookie ID, which you have to pass around anyway, no matter what, because that's what servlet sessions are built on.
This is pretty much the same approach as in 2), only in reverse. You have some sort of private servlet on server 1 that server 2 can use to lookup the user's session object over there and get the details, using an HttpURLConnection POST.
Note that with either 2) or 3) you have to take extra special care to secure the servlet to which you're POSTing. Probably your best bet is to use a J2EE security realm and use digital certificates for both authentication and encryption. In other words, you use SSL but instead of just having the POST include some sort of password, you actually generate a unqiue SSL-style digital certificate and install it in both app servers. Server 2 then passes that certificate to the first app server with the request, over an encrypted channel.
I'm hesitant to include this approach, because it's a kludge, but the thought occurs that you could use a simple cookie approach - set a cookie on the browser containing the username and password, then redirect the browser to the second server - with a fast-expiring cookie. The idea here is that even though you're using a cookie, which is technically vulnerable, you could set the cookie's expiration to 5 seconds later. I haven't tested this, so don't take my word for it.
People are funny, particularly the public. They will be extremely sensitive to the oddest things - for example, a user might manage to stop submission of the form in approach 1), view source, see their username and password, and freak out, even though they themselves just typed that username and password in.
To avoid this, you might use a secondary layer of "spin control" oriented security by adding simple private-key encryption on the cookie or form's contents before setting it at server 1, and having server 2 simply know the private key to decrypt it. I call this "spin control security" because it's not really secure, but it does keep people from freaking out. It does add a marginal amount of security, in that it makes the connection that much more secure and requires an intruder to sniff enough transactions and burn enough CPU time to crack the private encryption, so it might be a good idea in any event.