We are facing one issue in a Struts application deployed in JBOSS clustered environment with load balancer and sticky session
Issue description
1) This issue happens in a user registration functionality which has 2 pages, register1.do and register2.do page
2) When user clicks on registration url, https://ourwebsite.com/register1.do
Two GET request are made
GET register1.do (Gets 1st registration page and sets few values in session)
GET captcha.do (This loads a captcha image to be shown on register1.do)
3) Sometimes what happens is GET request to register1.do sets a JSESSIONID cookie and the GET request to captcha.do over write JSESSIONID cookie set by first request. This causes problem in 2nd registration page as it fetches some of the values stored in session and as the session is overwritten by captcha no values can be obtained.
see below image
4) This scenario does not happen every time, once this issue occurs and if we go back to register1.do page a refresh(F5)/hard refresh (Ctrl + F5) then GET request to captcha.do does not over write JSESSIONID cookie and user registration works fine.
Moreover this happens only in clustered environment, in single JBOSS environment it works fine.
Can anyone please help me to identify what could be possible problem
here ?
Why session does not get over written when we do a page refresh ?
Update your apache mod_cluster binaries to mod_cluster 1.2.6.Final which are available here.
This solved it for me, which was jumping servers after every single refresh. Hopefully that helps.
I also experienced the same problem with jboss eap 6.1 and in load balancer i'm going with mod_cluster configuration I changed algorithm from server per session to entry per session and sticky session is working well and good .Go through the following to know about entry per session and server per session.
Entry-per-Session means that the device creates additional client-table entries whenever a source IP opens a new session (unique source port). This gives the unit more accurate tracking of the number of sessions, but it's behavior is to continue sending all the traffic from the client's source IP to the same server.
In Server-per-Session mode, the device tracks the unique source ports the same way, but when the client opens a new session, the device makes a new load-balancing decision for the new session. This way multiple sessions from the same client IP can be 'sprayed' among all the servers rather than being stuck to a single server.
Related
The Problem
When redirecting from a servlet using response.sendRedirect(redirect_url);, the JSESSIONID cookie is not passed by the browser to the destination. A new JSESSIONID is created for every redirect, and it is impossible to track the user.
Note: This problem is only occurring on my new server implementing https and a domain name; the session ID is properly tracked when I run the web app locally or on another server without SSL or a domain name. Edit: I have set up another site on my server without SSL, and the issue persists. This seems to narrow the issue down to having a reverse proxy Apache.
An Example
The Login servlet on my web app attempts to store the user information in a session attribute then redirects to the MyCards servlet. I am using a redirect so that the URL will display mydomain.com/MyCards instead of mydomain.com/Login. The MyCards servlet attemtps to access the session attribute but finds nothing, and therefore redirects back to the Login servlet. This worked perfectly before deploying the project on my new server with SSL and domain name.
My Setup
Ubuntu 20.04 on DigitalOcean droplet
Apache Web Server (apache2) ... I have enabled mod_sessions, not sure if that's relevant.
Tomcat 9
Reverse proxy in Apache VirtualHost to Tomcat (I can post my .conf file if requested)
A redirect in Apache VirtualHost from HTTP to HTTPS
JDK 11
Possible Solutions
Using a forward instead of a redirect. The session ID is not lost when using requestDispatcher.forward(request, response);. As I mentioned above, I want the URL to reflect the destination for an intuitive user experience, which does not occur when using a forward.
Implementing your own session cookie, as in this answer, and manually storing sessions with a map, as in this answer, which strongly advises against such a facility. Based on my understanding, doing so poses security threats to user data. Also, if the browser is not passing the JSESSIONID cookie, I don't understand why it would choose to pass the manually implemented cookie unless the SameSite attribute is set to None (also bad).
Verifying that the webapp's context.xml does not have cookies="false" configured. Done that.
Using encoded URLs with response.sendRedirect(response.encodeRedirectURL(url));. Again, for the sake of having a clean URL (which the user could bookmark or type in) is preferable, and encoding the session ID into the URL is not.
Using relative URLs instead of absolute URLs...
"A session is only maintained if the redirection is being sent on the same port, host and webapp [and protocol?]. If redirection is done within the same application, using relative paths is the best practice." I tried both redirect_url = "/MyCards" and redirect_url = "MyCards", no luck.
Possible Reasons
Perhaps I am unknowingly switching between HTTP and HTTPS, which is a change in protocol and will not preserve the session ID. Of course, my intention is to remain secure and stay exclusively in HTTPS. Edit: I have set up another site on my server without SSL, and the issue persists. This seems to narrow the issue down to having a reverse proxy Apache. When accessing the web app directly on Tomcat (i.e. with <server_ip>:8080/MyWebApp), the session is tracked properly on redirect. However when using mydomain.com, the session ID is lost on every redirect.
Something to do with naked domains.
Other?
Edit: Maybe the issue is occurring because of the way the client, Apache, and Tomcat interact via the reverse proxy. Does the proxy cause the domain/port to change on every request/response?
My Questions
Why exactly is the session ID lost when using a redirect to a relative URL to a servlet in the same web app on the same server? Shouldn't the redirect occur entirely on the server-side, preventing a new request/session from being created? Since the relative URLs (which I thought would preserve the session) did not solve the issue, does this indicate some problem with my server setup (e.g. unintentional switching between protocols)?
What is the best practice for maintaining the user session ID, even when the user has cookies disabled? Is there no way around URL encoding when cookies are disabled? Or should the app be implemented exclusively with forwards rather than redirects? If so, is there a workaround to changing the URL to reflect the destination?
Note: this is my first post, so I don't have the reputation to comment. I will edit the post with any needed information.
What are "active sessions" in tomcat? I am trying to monitor active sessions for a Java web application. But the values I am getting are not matching with number of people using web application. Could you please explain?
Basically the number of active sessions is the number of existing or previous browser or other connections with an unique jSESSIONID cookie value. As soon as someone hits your webpage with a browser a new session is initiated and an unique JSESSIONID is assigned to this session. If next hit is performed with the same JSESSIONID (which is transmitted as cookie or url parameter) the session count remains the same. If the parameter is not transmitted a new session is created.
Usually all browsers keep the session id cookie over multiple requests and even multiple tabs or windows (except for incognito tabs/windows of course).
There are multiple reasons why your session count is larger than you user count.
Sessions are held in tomcat for a period of time, with 2 hours being the default. You can change this amount in tomcat settings. So if 100 user logins into your application in first hour, and 100 in second, your total session count will be 200, even if the first 100 users are idle.
Robots like the google bot tend to create tons of sessions. If your page is publicly available check the access logs if there are some bots visiting your page.
If your application is behind the loadbalancer or proxy which are continuously 'pinging' your application for its availability, this pings can create sessions as well.
Finally there are a lot of 'funny' ways your app can get requests from browsers, for example search results prefetching and similar.
Also keep in mind that session is bound to the domain name of the site. So if a user connects to your site via multiple domains (for example www.domain.com for content and static.domain.com for images) each of the connections will have its own session.
Now, there are different way to prevent unneeded session creation, depending on what your exact problem is (and if it is a problem at all).
If you have parts of your application that don't require a session ensure that you don't call request.getSession() somewhere in your code. Also in the jsp you can explicitly turn off session with <%# page session="false" %>
The the session timeout lower to make them expire quicker in tomcat/conf/web.xml <session-config><session-timeout>30</session-timeout></session-config>
The session-timeout value is in minutes.
Finally if you are interested in what is really happening in your application, get yourself an APM (application performance management) tool like MoSKito
I have a Tomcat 7 web server.
After login to it I can see under Cookies that there is jsessionid which, from what I have read is saving the id of the session instance between the user and the web server.
But the thing I cannot understand is that after I login and I stay in the browser.
I can stop the server, even un install it from the system and re-install it.
and then after I restart it I can continue navigating in the website without needing to enter credentials or anything like that, as if nothing happened in the background - I just can move on with the same jesssionId.
So basically I will divide my question into sub-question so it will be easier to answer:
1. How is it even possible that after stopping the service or even un install it it can still happen?
2. How excatly is the jesessionID created? I mean is it possible that it is the same jsession id?
3.When exactly does the jsessionID is being created?
4. Is it possible to change this behavior and "invalidate" the session so the user will have to re-enter his credentials?
5. Following question #4, what is common in most of the services? demand to login again or to enable the use of the old session id ?
Thanks a lot!
In answer to your questions:
Tomcat's session Manager will serialize session data and save it to a file to persist it across restarts. You can disable this.
Tomcat's SessionId Generator determines the exact way the id is created.
Here a good answer for when session ids are created: Under what conditions is a JSESSIONID created?
If your goal is to invalidate sessions after a Tomcat restart, you can do this by disabling session persistence.
Typically a user would want to be considered "logged in" until they click a "log out" link or button in your application. You can also adjust the session expiration time if you want the session to expire after a period of inactivity. How exactly this should work is up to you and depends on your application's use cases.
I have a web application in Tomcat 7 which keeps user information in session as a DTO object. I also have Spring security enabled for my project which automatically redirects a user to a login page if the user does not have a session.
If I log in to my application once and then I restart Tomcat in Eclipse what happens is that my session gets flushed out but the cookie does not go.
What this means is that after server restart there is no UserDto in session but a valid JSESSIONID remains with browser. Thus spring security still thinks that the user is logged in when in fact he's not.
Why is this happening? (I have check the type of JSESSIONID cookie by viewing page info in Firefox it says - Expire: At end of session. Thus it should ideally expire at server restart or shouldn't it?)
Edit: Though Firefox says Expire: At end of session the cookie is still there if I close and restart Firefox.
From Servlet 3.0 to add expire date to a cookie you can add cookie-config to your web.xml file
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<max-age>1800</max-age>
</cookie-config>
</session-config>
The cookie is held in the browser - when the server restarts, but the browser continues to run, it will hold onto the cookie and present this to the server on next request.
Now on the server side, you have multiple options: You can configure tomcat's SessionManager to persist on disk and read the content upon restart - this is an option that also is used to distribute sessions between multiple tomcats in a cluster: When the session is serialized to disk, any server can continue the session by "just" deserializing it. There's some cost implied (as you constantly need to serialize sessions)
Currently I can't give you more concrete hints than this - but if you look it up and understand the difference between where the cookie is stored, why it doesn't change on server restart and that you'll have to look up tomcat documentation of the session manager, you'll hopefully manage to figure it out.
Tomcat will generate a JSESSIONID automatically if you have used session in you web project.
If the session id changed then the JSESSIONID will changed corresponds. Because
the JSESSIONID indicates the seesion ID of the WEB project.
It will expire when the server stop(in default it will expire within 30 minutes), but the cookie cannot delete automatically.
JSESSIONID can configs in server.xml file of tomcat.
While you log in succesfully, SpringSecurity stores a cookie in your browser.
When the browser sends a request, SpringSecurity checks what's in the cookie. If SpringSecurity finds the value it stored before, it thinks you have logged in, so SpringSecurity won't redirect to the login page.
One browser means one client but what if two browser from same machine?
I think it should be considered as one client because I see the similar session id for any no. of browser. Anyway keeping these things in mind, I have an issue.
A client send file and server's application create a unique folder in context to save file.
unique folder : it is auto created & for each client.
so my question is, is session id perfect solution for unique folder name ??
#Edit : An application upload multiple files in a auto-created folder from client to server and provide a link to download the same folder to same client.once the client downloads the folder(all files), it is removed otherwise remains for next couple of hours(programmed).
what if there are many clients uploading the file, then how should I avoid the duplicate folder name? So I thought to autocreate folder on the basis of session-id
Using the session id will give you one folder per session.
How the client relates to sessions depends on several things: usually, different browsers (ff, ie, etc) do not share sessions, so each new browser will have it's own session with your server - irrespective of the machine on which the browser is running. If the user opens multiple windows using the same browser, they will share the same session if using cookies, but have different sessions if the sessionId is embedded in the url.
Edit: if the sessionId is in the URL, you can in fact get any browser on any machine to share the same session by copying the URL, with the sessionId, into the browser.
Yes session id seems to be fine.
Session_id can indeed be duplicated, but the probability is very low.
If you have a website with a fair traffic, it may happens once in you
web site life, and will just annoy one user for one session.
This is not worth to care about unless you expect to build a very high
traffic website or a service for the bank industry.
-> How unique is the php session id
don't you have an authentication system? if users get logged in, user id is the one you need to use. so, even if two different users logged in from the same machine, they will have two seperate folders. if you don't require authentication, maybe you can force to get a new session id for the first connection.