I have a website under a domain called www.example.com.br. And my server is set to work with cookie session tracking mode.
getServletContext().getSessionCookieConfig().setDomain(".example.com.br");
getServletContext().getSessionCookieConfig().setPath("/");
But now I'm introducing an english version of the website under www.example.com, because for Google and SEO techniques it's better to have different domains instead of a subdomain.
I found a lot of questions in Stack Overflow about this, and I know it's impossible for a lot of security reasons.
But isn't there anyway to tell Tomcat to work with a cookie domain .example.com.br if the URL has .com.br and .example.com if the URL has .com? I don't need to share session information... ie: the user may have to login again if he changes the domain. I'm not worried about it. The problem is that no information on the .com version is been stored at all, because the cookie is set to .com.br version.
Isn't there any workaround for that?
It is user's browser that decides whether to send the cookie with the request or not. Web server (Tomcat, in your case) does not have any say in that decision. What you are asking for explicitly forbidden. For example, RFC2109 says:
A user agent should make every attempt to prevent the sharing of
session information between hosts that are in different domains.
The best recommendation I can make is to make your session management (login, logout, ...) work off a single domain, regardless of what domain user originally accessed.
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.
I promised to do something, but my managers want assurance that it can be done. What seems like a simple task is surprisingly hard to find example of. It consists of:
The browser asks a Java servlet for access to a remote site.
The servlet opens a HttpUrlConnection to that remote site.
The servlet sends a login request to that remote site.
The servlet receives a login form.
The servlet populates the login form from user session data, then
POSTs it.
The servlet receives the "welcome" from the remote site, complete
with headers and cookies.
The request of step 1 is finally filled by the content, headers, and cookies from step 6.
I'm having trouble getting code examples, leading me to think that what I want to do can't be accomplished. Can someone point me to an example?
Thanks,
Jerome.
The main problem is the domain of the session cookie.
More accurately, the question is what you're planning next after step 7.
Say your servlet is at "https://mycompany.com/loginServlet", and the remote site is a toy store "https://toys.com". Were you hoping that after step 7, the browser could be redirected to "https://toys.com" and get a proper service befitting a logged-in user? This won't work because when the browser received a session cookie from "mycompany.com" (in step7), this cookie will be attached to further requests for "mycompany.com" - but not to "toys.com", it's a security feature for excellent reason.
In short, this approach might work if both the servlet and the toys site are on the same domain. Though it makes me a bit uncomfortable in terms of security and password management, but never mind.
Obviously this approach would also work in the (unrealistic) case of letting your server proxy all further requests from the browser to "toys.com", but that's unrealistic for a typical commercial site (due to relative/absolute links, ajaxes etc.).
If it's different domains, then I second the wise comment made by "Rahul B" above: please look into SSO, and/or check with "toys.com" what login mechanisms they offer - maybe they already have something like "login with google" that's convenient enough.
I know following are the ways to maintain or session tracking in java but looking for a good one
URL rewritting
Hidden form fields
cookies
Session object like setAttribitute() and session.getAttribute()
If the client browser has blocked accepting and storing cookies then last 2 ways are not valid.In hidden form fields I need to pass the hidden values in each and every page inside form.So suppose If I am just using response.sendRedirect() Then hidden form field is of not use.The remaining is URL rewriting in which I will pass JsessionID in the URl.So My question by knowing the sessionID isnt the unauthorized persons can able to access the pages.
For example There are 3 pages login,register,send.So after login user can register and/or send.So if any one knows the sessionID cant he/she go direct to register/send page.If yes Please tell me how to prohibit this
As of Servlet 3.0 (Apache Tomcat 7 onwards) if you use SSL then you can configure your application to track sessions based on the SSL session ID. The downside is that everything has to be over SSL. The advantages are that the session is strongly tied to the SSL connection. Only the user that created the connection to the server that has the correct SSL session has access to the session. Even if an attacker knows the session ID, they can't access the session.
One word of caution, this form of session tracking is the least widely used so it may not have been as heavily tested as the more usual cookie and URL re-writing mechanisms.
Have a look at this link which outlines Best practices for using HTTP sessions
Including
javax.servlet.http.HttpSession.invalidate()
Use HTTPS
With standard solutions you can't.
You can add some measure of security by adding request originator IP address verification, but that's also fooled easily. (to clarify some here means very tiny itsy bitsy little bit of)
So the secure route is to not use URL Rewriting to maintain session in secure application.
However you may be able to get some security by keeping the JSessionID as a separate encrypted attribute that which will be decrypted by a middle-ware or a load balancing server sitting between the client and your application servers. This of course is just a thought, I haven't, fortunately ever had to try something like that out :-)
Session tracking & authentication are two diff things don't club them.
Understanding your requirement I see you want to secure the sessionid of the user.
Evasdroping: If someone is listing to the request & response in the middle he can take the sessionid and use it. The best way would be to use a SSL. This ensures no one is listening in the middle.
Sessionid stolen from Client side: Normally this should be taken care by the browser and OS. So your user is as secure as the system he has.
What would be good/scalable user session alternative in following scenario:
users don't have to have cookies enabled
URL query string restriction of 255 characters is imposed
lot of GET requests (no hidden form fields)
application runs on several servers (web farm)
some users connect over proxy (same IP)
users connect over HTTPS
50 000 concurrent users
If you can guarantee that the client always connects to the same web server, you can use the SSL ID as a simple session tracking mechanism. Some web servers expose this capability and automatically use it for session tracking when cookies aren't supported.
The only solution that will work no matter what is to include a session ID in the URL itself. Adding a parameter to the URL is the simplest way to do this, but the ID can be embedded anywhere in the URL, i.e. as part of the path. You would use this ID to fish information about the user out of a database.
You will run into the usual problems, of course, with ID spoofing and having the session database be a bottleneck.
First, IMHO, there is no good alternative to session. The question is how do you obtain it when cookies are disabled. The answer is using URL parameter. So, you have to append session id to each request (including links and forms). All other requirements are not really relevant. Make your logic stateless, so you do not have scalability problems: all requests should arrive to your logic via load ballancer, so you can add as many servers as you want.
Maybe URL Rewriting or some URI shortening mechanism like http://tinyurl.com or http://goo.gl so you can pass your session details well under 255 chars.
Note: Not recommending to use these services but the mechanism.
First of all, your requirements are very tight.
The only option I see is using an approach like this: http://code.google.com/p/seaside/
In short: your system will generate statless urls like
http://host/app/#123445568978
Then you will go on the db to get the session object.
50000 users doing what? Continuous drag-and-drop with position updates to the server or clicking a text link every 15 minutes? In the last case: move everything onto a single server with a lot of ram.
If a user opens 2 web pages simultaneously they will create 2 sessions.
Usually this would not matter but it does create a problem for remember me functionality when attempting to rotate cookie tokens as recommended in the persistent login cookie best practices. There seems to be no way to rotate both cookies correctly where both sessions are opened simultaneously.
How can I resolve this?
I use Tomcat and Struts 1, but I think this is framework independent.
extending #Thilo answer He is correct, any subsequent access to other page will follow send the cookies for that domain. e.g open gmail, login and now open gmail in other tab or window it send the cookie for that domain. since the cookie hold the session information on any subsequent request only session id/value will be changed.
You can check it using firebug and its extension fire-cookie.
On matter of avoiding remember-me problem as said in the link you specified it is more to design problem as how you are handling it.