During some debugging of our WebLogic application, I've noticed that the JSESSIONID doesn't change after the user logs out.
I'm trying to understand if this is something I need to be concerned with.
This application is one of two applications running within a WebLogic instance, and I notice that they both share the same JSESSIONID.
This question makes reference to the following:
SRV.7.3 Session Scope
HttpSession objects must be scoped at the application (or servlet
context) level. The underlying mechanism, such as the cookie used to
establish the session, can be the same for different contexts, but the
object referenced, including the attributes in that object, must never
be shared between contexts by the container.
This suggests that ultimately it's up to WegLogic to choose how to manage these JSESSIONID values, and I should not try to interpret meaning from the change in value (or lack thereof).
Additionally, I've wired up an HttpSessionListener on the application, and I see the sessionDestroyed method get invoked.
Given these two elements, it seems safe to me that the JSESSIONID is not changing. However, this is different behaviour from what I'm used to, so would like to verify my assumptions.
Is it a security concern that the JSESSIONID doesn't change?
No, it shouldn't be a huge security concern, since all the data that was actually associated with that session is discarded. The JSESSIONID is just a key to that (now nonexistent) data.
However, if you want the JSESSIONID to change on each logout/login, you could just implement your logout functionality such that it explicitly deletes the JSESSIONID cookie when the user logs out. Then the server will allocate them a brand new session/id on their next request.
Of course, as noted in the documentation, if you have multiple contexts that all happen to be relying on the single JSESSIONID cookie, then deleting it from one will essentially delete it from all, effectively logging the user out of every context on your server. Although in practice, it's not hugely common to have multiple user-facing contexts, each with its own login/session state.
Related
I’m trying to understand how we build a RESTful API for a SaaS product where it involves multi tenancy. The technology stack is Java using Spring and Hibernate and deploying a WAR to Tomcat.
My main issue is how do we maintain the tenant_id within the REST call in order for the application to use the correct database connection when performing CRUD. Seeing that Tomcat uses a thread pool and reuses threads we should not use ThreadLocal.
I have read that slf4j supports this with the MDC implementation for logging. A servelet filter does maintain the tenant_id upfront and clears it upon exit of the filter. Therefore, the logger uses the correct tenant_id in the messages.
At the same time using a ThreadLocal goes against the principle of stateless as this implicitly adds a state.
Furthermore, the idea of creating some kind of ContextSession object holding the tenant_id and passing it around does not seem to solve my issue. As this object would be passed down the layers of the DAL and DAO to load the objects. I want to avoid this high coupling on this ContextSession class, as well having to include it on many method signatures.
How do I implement multi tenancy in a stateless environment?
When a user logs onto your application, they would be somehow associated with a tenant. So the tenant information should be accessible from the spring SecurityContext.
As an example, if i have an application with 2 tenants; tenantA and tenantB. When logging on, the user needs to indicate somehow which tenant they belong to. This can be done in various ways, such as using different host names (eg. tenantA.myapp.com, tenantB.myapp.com) or url parameters, or entering the tenant information on a logon form. When authenticating the user, you then need to use the authentication realm associated with the particular tenant. As part of the authentication, the spring SecurityContext should be setup to contain information that lets you determine which tenant the user belongs to on subsequent service calls from the user. The SecurityContext should be accessible from different service layers of your application without you needing to explicitly program anything for that to happen.
There are a variety of ways to associate your current HttpSession to a specific tenant.
Provide some type of client_id parameter on the URL that is used to reverse lookup the specified backend tenant through a centralize common client database.
Associate an authenticated user to a specific tenant. When users authenticate against a centralized user database, the tenant is looked up based on the user account.
How that tenant_id is passed to the lower application tiers is really a matter of taste.
My first option would be to use a ThreadLocal. If you're already using Spring Security, you're already using ThreadLocal variables and may not even be aware of it.
The use of ThreadLocal variables do not break the stateless design of your application. You just have pieces of code that expect a variable to contain a specific value that it must use. It's just a fancy way to pass state across your application tiers without actually explicitly passing it as arguments on a method signature.
Obviously the other two options are to use some Context object or merely pass the value directly downstream.
In a web application, I would typically do this via some interceptor or filter that would per request lookup the request parameter client_id and get the associated tenantId and set that in a special ThreadLocal variable.
Once the call to chain.doFilter( request, response ); has returned or throws an exception, you simply then clear the ThreadLocal variable.
I need to redirect from one domain into an another. Hence I am using sendRedirect(url). But i need to also get few attributes which were set in session. Is there any way to get the session attributes after using sendRedirect(url)?
Normally it's impossible to access one application session from another. If you're redirecting you can pass required attributes in the url (but maybe it's not the best idea, conisder security for this approach). Some servers may have some magic tricks to share sessions between applications deployed on the same server (I think it's possible in weblogic)
So, I'm in the middle of building an application where I want the user to be able to send a link to another user and work on the same data. There is little need to persist the data for more than 15 minutes and I want the application to not have to rely on a database.
I have a few variables which I am currently storing in a HttpSession.
Ideally I'd like to be able to set a parameter "sid" in the URL, and use that to set the session ID on the second client's browser - the one that's received a link with the SID.
Unfortunately, there seems to be no way to change the SID of a current session once it's been set up.
The only solution I've come up with so far is referring to the doGet() with a HttpPost.setHeader("Cookie", "JSESSIONID="+ getSessionId()) method, and getting the data with a specific session that way, but this seems pretty clunky.
Any suggestions?
EDIT
This has seemingly turned into a discussion about the wisdom of setting two users up to have the same session so session vars may be kept the same. Note that a non-db, ie light weight solution was what I was looking for. PHP allows you to arbitrarily set a session ID to do this, but I'm deploying to Tomcat in this instance. Something which allows lightweight sharing of a few parameters, that's it...
What I've done, then, is to set context vars using context.setAttribute(). Ugly as sin, but all I can come up with, unless anyone has any better ideas.
This approach has some security issues because you are simulating [session hijacking] with it 1:
In computer science, session hijacking, sometimes also known as cookie
hijacking is the exploitation of a valid computer session—sometimes
also called a session key—to gain unauthorized access to information
or services in a computer system. In particular, it is used to refer
to the theft of a magic cookie used to authenticate a user to a remote
server. It has particular relevance to web developers, as the HTTP
cookies used to maintain a session on many web sites can be easily
stolen by an attacker using an intermediary computer or with access to
the saved cookies on the victim's computer (see HTTP cookie theft).
Better approach is to set your data in a way that both users can approach it from their sessions. If you are using single server you can do that with some global data within a server. In clustered or cloud environments you'll need some common storage for that (ie. database, global cache, etc.)
EDIT
You are on a right track to share data among two users with different sessions.
There is one context per "web application" per Java Virtual Machine
where an attribute allows a servlet container to give the servlet
additional information.
Attributes are meant to be used to share data inside container among servlets of the same web application.
For clusters:
In the case of a web application marked "distributed" in its
deployment descriptor, there will be one context instance for each
virtual machine. In this situation, the context cannot be used as a
location to share global information (because the information won't be
truly global). Use an external resource like a database instead.
I'm trying to fully understand when/how to use CloudBees' notion of application session stores.
After reading that article, my understanding of them is that they provide a way to make multiple instances of your appserver share persistent session variables. That way, you can load balance between each server, and it doesn't matter which instance your user gets redirected to; each server instance has the same shared session states (for all users).
So first, if my understanding is incorrect or slightly misinformed, please begin by correcting me!
Assuming I am more or less correct, then I have the following questions:
How does this hurt performance or memory utilization? I would imagine that if each server has to share the same cached session data for all users, it would get kind of bulky and perhaps even pricy...
Is there a way to programmatically CRUD session states (i.e. flush the cache, inspect it with JMX, etc.)?
Can someone provide a concrete use case for this feature, just so I'm positive I "get it"?
Thanks in advance!
Session store let you replicate the HttpSession around the cluster, so that you can scale-out application load on multiple instances, without having to stick a user to a specific server (this is the other option you can use : configure sticky session)
By nature, serializing HttpSession data has some impacts on performance, but as it uses a memcache backend this is minimal. This also mostly depends on the amount and size of objects you store in user session. Also, please note this require you explicitly put object in HttpSession after any attribute change, even the object was retrieved from session - this is a general API issue with JavaEE clustering.
You can't programmatically query the session store (you could with the adequate memcache client code, but this doesn't make much sense)
Two concrete use cases
application distributed on multiple nodes, with session distributed around the cluster, and without sticky session so that load is actually distributed for ALL user
Application te be redeployed can't suffer user session to be lost, to ensure a continuous 0 downtime service. version N+1 application will then retrieve httpsession data from version N, need to be compatible from serialization point of view, but connected user won't notice the redeployment and version upgrade
I work on a task that involves moving/traversing from one application to another. The applications are in separate JVMs.
While traversing to the other application, I keep track of the session ID. However, as I traverse back and forth, a new session gets created. Is there any way for me to get back the same session, using the sessionId that I retain, when I navigate back into my parent application from a child application?
Environment: J2EE with WebSphere.
As mentioned by Mork0075, the sessionID is tied to the cookie name and the server domain. If you're using the same server domain for two apps on separate JVMs, I see two options to maintain the session when switching between applications:
The long shot:
1) If you're using a database for session replication purposes, you can use the same database for both applications, and the sessionID will be available for both apps. The one problem I see here is that the objects in the session may not be available on both sides, since the code would be different etc. They'd probably clobber the other side's session objects unless you maintained the code and such on both sides so the objects were available.
The likely possibility:
2) Use different cookie names for the session on one of the two apps. By default, sessions use JSESSIONID as the cookie, and when you switch to the second app, it tries to look up a session based on that cookiename and can't find it. So, it creates a new sessionID and sends it back to the browser, thus causing your sessionID to change and not be available when you switch back to the original app. However, if you change the second app's sessionID to something else (say, JSESSIONID2) your browser would end up with two valid sessionIDs that would each be valid on their correct application. You can change the name via the administration console under the application server's Session Management->Enable cookies page.
I'am not sure if this helps, but in a ONE application scenario, you would submit a sessionID with every reponse, save it in the URL, a cookie or as a hidden field. By submitting a new request to the server, the sessionID is also submitted, to resolve it at server side. In my understand switching from one application to another means, that you have to give the sessionID with the user, across the applications. If you save the sessionID in a cookie, this perhaps is not possible, because the cookie is restricted to a certain server domain. So ensure that the session is still valid and the sessionID is present after returning to the application started.
You shouldn't have to do this manually. Most app servers support Single Sign On (SSO) so that you can log in to one application and have access to all the applications in the same SSO domain. The app server will keep track of session ids and link them to an HTTPSession object specific to the web app.
See http://publib.boulder.ibm.com/infocenter/wasinfo/v6r1/topic/com.ibm.websphere.base.doc/info/aes/ae/csec_sso.html