Distributed HTTP session state server for tomcat - java

One of our Spring MVC web application is deployed on multiple web servers with tomcat 7 and LB is at front to balance and distribute the requests to appropriate tomcat server.
Problem with this web farming is each tomcat server is able to store and retrieve its own HTTP session, but LB can send requests to any one of web server. So if a user is served for login page through tomcatServer1 then it's HTTP session will be created on it's respected server and it may happen that for second request of dashboard page LB sends it to tomcatServer2 where HTTP session is not available, resulting user is again redirected to login page.
To overcome this,
we are using "Sticky Session" property on LB, so that if a user (HTTP session + user's public IP) is first time served from tomcatServer1 then it will get bound to that server. Setting "Sticky Session" is not helpful as it's not utilizing all servers equally.
Another way is, develop our own session state server and deploy on a server then all server should communicate to that server for storing and retrieving session object/data.
Providing custom SessionManager to Servlet Container.
About #2, If in case we able to develop state server then also I have to modify the code to related to HttpSession.setAttribute() and HttpSession.getAttribute(). So question is, is it possible to override implementation of HttpSession for methods setAttribute & getAttribute? Also About #3, I don't know whether this solution will provide distributed state session server?

I developed session state server for tomcat using python.
Due to this I don't need to change the code already written for creating/accessing and destroying session. Also as there is separate server/service which is handling and storing session so not master cluster is needed.

Related

Two instances of tomcat running same application create same sessionId for different users(?) [duplicate]

One of our Spring MVC web application is deployed on multiple web servers with tomcat 7 and LB is at front to balance and distribute the requests to appropriate tomcat server.
Problem with this web farming is each tomcat server is able to store and retrieve its own HTTP session, but LB can send requests to any one of web server. So if a user is served for login page through tomcatServer1 then it's HTTP session will be created on it's respected server and it may happen that for second request of dashboard page LB sends it to tomcatServer2 where HTTP session is not available, resulting user is again redirected to login page.
To overcome this,
we are using "Sticky Session" property on LB, so that if a user (HTTP session + user's public IP) is first time served from tomcatServer1 then it will get bound to that server. Setting "Sticky Session" is not helpful as it's not utilizing all servers equally.
Another way is, develop our own session state server and deploy on a server then all server should communicate to that server for storing and retrieving session object/data.
Providing custom SessionManager to Servlet Container.
About #2, If in case we able to develop state server then also I have to modify the code to related to HttpSession.setAttribute() and HttpSession.getAttribute(). So question is, is it possible to override implementation of HttpSession for methods setAttribute & getAttribute? Also About #3, I don't know whether this solution will provide distributed state session server?
I developed session state server for tomcat using python.
Due to this I don't need to change the code already written for creating/accessing and destroying session. Also as there is separate server/service which is handling and storing session so not master cluster is needed.

Java - How to share the session between two or more Web Application?

I have two web Applications. I will login in to one Web Application and will navigate to another by links or redirection from the first Application. Lastly after completing some steps in Application two, I will be redirected to Application one. How can I implement this?
Here Application two is generic, and I will have three instances of Application One, which will interact with Application two.
Please suggest a better approach. I have to use spring and Spring Webflow to implement it.
Technically, session between two web application (two different WARs) cannot be shared. This is by design and done for security reasons. I would like to make following comments and suggestions for your problem,
Session are generally tracked using an session ID which is generally stored as a cookie on the browser and Session object on the server side.
This cookie is sent server side every time when you send a request.
A cookie will be sent ONLY to the server where it came from.
So a cookie set by www.mysite.com/app1 will be sent only to www.mysite.com/app1 and not to www.mysite.com/app2.
For you case, for a user sessions to be valid across two application, the browser will need two cookies to be set from app1 and app2.
One way would be, when you login to app1 , using java script, also send a login request to app2. When both these request return successfully, your browser will have session for both the applications (app1 and app2)
Now logout will have its own challenges, when you logout from app1, you also need to logout from app2. Technically this means, you need to clear the cookies set from both of these applications. With little help from java script you can do this.
When you have to make a call to app2 from app1, pass all necessary information via the request object (as a request params) then app2 can read and create the session there (perhaps a servlet/filter can be used for this).
you can share a session between the same application (app1 and app1) across machines using clustering.

Servlet Acting as Proxy: How to forward the session?

I am not too sure about the feasibility of the requirement that I am trying to achieve, but here is how it goes:
I have created a Servlet that acts as proxy. It receives a RESTful call and then invokes another RESTful service on a remote server (node).
The forwarding is achieved via HTTPClient and not with a Request Dispatcher. I basically issue a new HTTP request to the remote server.
When the first server (proxy server) receives the call, the request (HttpServletRequest) has a session associated with it. The isNew() property of the HTTPSession is false.
When the call is forwarded and the remote server receives the call, the session gets to be a brand new one.
I am trying to basically find a way to forward the session to the remote server as well.
To be more precise:
Is it possible simply to get a session from a HttpServletRequest and put it into a session of a newly created HTTP request (via HTTPClient)?
It depends on how your remote WS maintains a session. If for example, it uses cookies (Tomcat does that amongst other techniques), then forwarding the incoming headers should help you achieve that (make sure that you mention that you accept cookies, but I thing HTTPClient does it by default).
Now, if it is based on parameter in the URL, then you should try to reproduce that behaviour.
If the two nodes (proxy and service) are separate processes that are not part of an application cluster, then probably not.
The servlet container typically manages the HttpSession. If you are forwarding a request to another service, hosted by a different container, then you will have a different session object.
If the two nodes are part of a cluster, then typically the session can be shared between nodes in the cluster via a number of mechanisms (in memory replication, database synchronization, etc).
Another option, is to externalize your session data into something like Redis, Memcached, Coherence, etc. Some application servers have pluggable support for such a process. I believe in this scenario the application server nodes would not necessarily have to be party of a cluster to share the session data.
I lacked some of the fundamentals of session handling when I asked this question. After some research and discussion here is what I got:
Basically, the sessions are handled by a JSESSIONID variable.
JSESSIONID is created automatically (can be turned off) when the request hits the server.
It gets sent back with in the response header.
The reason why the remote server thinks it is a new session is because the request doesn't have this JSESSIONID set.
The proxy does the following to ensure that the session is forwarded:
When the incoming request comes in; create and store the JSESSIONID.
Issue a new request to the remote server.
Unpack the response header from the remote server and extract JSESSIONID.
Maintain a mapping of client side JSESSIONID and remote server JSESSIONID.
For any of the following request, use this mapping to send requests to the remote server.
Basically, the proxy does the mapping from the client side's JSESSIONID to the remote server's JSESSIONID. This way, the session gets forwarded to the remote server.

Session handling on Java EE application

I’m developing a system to process financial transactions received by client merchants systems & it is a replacement of existing system which we have purchased from a vendor. Client interface should invoke the user authentication & transaction processing screens from our system.
System functionality as follows,
Receive input parameters from the merchant’s site
Validate it
Authenticate users (users are registered with our system & we should invoke our login screen)
Process transaction
Return status response to merchant
One the response is received client should validate the transaction data from the values reside in the session.
System overview can be depicted as follows,
(click here for full size image)
My problem is client could not retain the session once we are responding to the client. But the same functionality could be achieved by the system that we have purchased from the vendor (we don’t have source code of this to analyse the internal coding structure). I hope something wrong with the way that we are responding to the client.
How can I overcome this problem?
We are using Java 1.4.2, Websphere application server
There are many things which can make a session disappear. I'd suggest to track them and verify if anything went right. This is easier to do if you understand how sessions work.
Session has been timed out. This usually defaults to 30 minutes. This is confiugureable by <session-timeout> in web.xml where you can specify the timeout in minutes. You can implement a HttpSessionListener to track session creation and destroy using a logger.
Session has forcibly been invalidated. This happens when the code calls HttpSession#invalidate(). This is trackable with a HttpSessionListener as well.
Session cookie has been disappeared. Sessions are backed by cookies. If a session is been created, the server will add a Set-Cookie header with session ID. The client should send the same cookie back as Cookie header in all subsequent requests on the (context) path as specified in the Set-Cookie header. This is trackable in the HTTP traffic monitor ("Network" tab) of browser's builtin web developer toolset (press F12 in Chrome/Firefox23+/IE9+). Cookies are accessible for all webapps on the same cookie domain. Also, if ServletC2 runs on a different webapp context than ServletC1, then it won't use the same session. Further, if the "server" webapplication runs on the same domain, then it's in theory able to wipe out all cookies of the "client" webapplication.
The client doesn't support cookies. A well designed webapplication uses URL rewriting with jsessionid to track cookieless clients between requests on the same webapplication. But the second webapplication has to do the same when redirecting back to the first webapplication.

How to transfer session from one Tomcat server to another?

We have a Tomcat server for a web shop, and we need to transfer the user to another (secure) server when he/she logs in. Here's a detailed explanation:
1) We have two Tomcat servers: one 'regular' (HTTP) and one secure (HTTPS)
2) Users initially visit the regular server
3) When they log in, we need to get their log in data, as well as the information about what page they were currently on (or were trying to see), pass it to the secure server and do the actual login; for instance, a non-logged in user sees a list of products, clicks 'BUY' and a popup is displayed, asking the user to log in; the user enters his/hers credentials and these, as well as the information about what product he wants to buy, are passed to the secure server; the secure server receives these, performs the login and displays the requested product to the user
How could this be done? Please note the following:
1) We've tried doing it with cookies, but we've decided not to go that way
2) Persisting the session to a database and then having the secure server fetch it is also not an option
Are there any other ways? We were thinking about creating an object and then passing it as a HTTP POST parameter, but I'm not sure how this could be done (I've been given the task to finish it).
For what it's worth, the technologies we use are Tomcat server, Wicket, Spring, iBatis and MySQL.
Thanks in advance :)
If you want to share the session between different Tomcat instances, you could configure them to work as a cluster with session replication: http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html
Then, you could configure an Apache HTTP Server to work as a load balancer, making sure that HTTP requests go to server 1 and HTTPS requests go to server 2.
But, you could also have only one Tomcat instance (or N identical instances) configured to handle both HTTP and HTTPS, and ensure the secure access with standard (...<transport-guarantee>CONFIDENTIAL</transport-guarantee>... in web.xml) or framework-specific configuration.
Not sure if I'm getting the gist of what you want but you could have the "pop-up" be a page served from the secure application to a protected URL. That would cause the authentication to occur at the secure server and you could go from there. For example, if the unsecured product page is on www.domain.com/browse/id1, then the "buy" button would open a pop-up to secure.domain.com/buy/id1, causing the authentication while transmitting the product id on the URL.

Categories

Resources