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.
Related
I have two war files such as war1 and war2
If am login the application, the session will be created in war1 and from that if am navigate to war2, there i need the same session data.
I tried crossContext=true in context.xml of server from that i can access the data by storing it in servletContext.
But the issue is once i logined the screen in chrome the session data will be stored in servletContext and the data will maintain till the application is running.
If am giving the same URL in another browser like IE here also, i can get the servletContext data so instead of navigate to login page the corresponding screen will be opened
Kindly suggest me how can i overcome this issue in java?
Is there any way to findout browser switching or incognito window mode of the browser in java?
Note: am using tomcat server
I have never dealt with your exact configuration problem, but even if you can make this work on a single Tomcat instance, you might have problems should your two web applications ever be distributed across multiple Tomcat instances.
So, I am going to suggest that you actually use a database to store state which needs to be passed between the two applications in a safe and reliable way. Note that the database approach also scales nicely in a distributed environment, so long as you have a single logical database.
While session replication indeed can be done in Tomcat (see here) I really suggest you to avoid this type of issues by eliminating the session altogether.
This session replication is an approach that was somewhat common before ~15-10 years, but nowadays when we have a lot of servers running in parallel to serve user requests and have elastic clusters, this approach is not good enough because basically it doesn't scale well.
There are many ways to achieve what you want, though:
Use a shared database to store the session information. Add some session Id to the response and require the client to pass this id back into all subsequent request along the session. Then execute a query to the Database by this Id and retrieve all the session information.
This solution also doesnt really scale well, but then you can shard the session information if the db permits to do so...
Use Redis/Aerospike to save the session information of the currently connected user. somewhat like DB approach, but since redis run in-memory it will be much faster. In general, this approach can be used in conjunction with 1 where redis is an in-memory cache.
Encrypt the session information or even just sign cryptographically and send back to client. Client will have to supply this information along with the request without knowing which server will actually serve this request.
Without delving into cryptography I'll just state that encryption can be done if you don't want client to see the session information (despite the fact that this is the user whose information is supplied) and signature is used to prevent tempering the data (while sending it back to server).
The data can be supplied to server from client via Header or cookie for instance.
I have been testing a web application with Spring MVC, and I'm currently developing a editor page for accounts. This JSP page is able to edit one or more accounts, serving for different purposes. For example, a common user can edit account data on this page. On the other hand, administrator users can edit multiple accounts on this page. In terms of logic (for me), the edition of multiple accounts to an administrator user works like this:
The user selects a list of accounts.
The list reaches the controller.
The controller stores the list of accounts.
The controller directs the user to the edit page.
The user fills out the editing form.
The form is sent to the controller.
The controller retrieves the list of accounts previously saved.
Editing form data is reflected in the list of records.
The list is deleted from storage.
My problem appears when the user does not perform step 5, and decides to do something else. Without the removal of the list from storage, the server will suffer from memory leak. It would be very important to detect the user's exit, which would cause the system to remove the list automatically.
I'm choosing to save the list of accounts to be edited on the server side to prevent it from being saved on the user side, where the user could well tamper the data.
I might as well use JavaScript to detect when a user leaves a page, but he/she may well turn off Javascript, which results in the same problem. Therefore, this is an impractical solution.
I have not yet developed the implementation of it, so I'm just projecting right now. Can anyone help me with this? Am I doing something wrong?
Is there an error in my logic, or am I leaving something of use?
OBS: I'm using Tomcat 8.0, and Spring MVC 4.1.1, with the Java JDK 8.
That's the whole purpose of session management. Your web server does it for you.
When you use Java EE or any other session technology, the server is supposed to deal with timeouts, cleaning the session objects. This happens based on user idle time. How does the server know users are idle? Because for every request sent by the browser, his session id is sent in a cookie.
Usually, the timeout threshold is a changeable period of time (usually defined at web.xml). This value may need to be tuned, based on the available network/memory resources and expected simultaneous users.
In fact, sessions+cookies are the only flexible and secure way to deal with the stateless nature of HTTP.
There are variations of this, namely, conversation or view scopes, where the user may have a session per tab. But the principle is the same: put stuff in session and get them later by session id (a cookie at client side).
Finally, you should not rely on the browser to do server stuff. This would not be reliable.
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)
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'm working on an existing j2ee app and am required to remove some vendor specific method calls from the code.
The daos behind a session facade make calls into the ejb container to get the user's id and password - in order to connect to the database. The user id and password part of the initialContext used to connect to the server.
I am able to get the userid using sessionContext.getCallerPrincipal()
Is there anyway to get to the SECURITY_CREDENTIALS used on the server connection or, is there a way to pass information from the server connection into the ejbs (they are all stateless session beans).
This is a large app with both a rich-client and web front end, and in a perfect world I'd be happy to go back and re-architect the entire solution to use J2EE security etc - but unfortunately, that is not realistic.
I can't give you a generic solution, but this is what has worked for us. We have the app server connect to LDAP as a specific user that has the ability to request credentials for other users. Then we have some generic security code that we can use to request a users credentials from inside the session beans, based on the users identity from their initial login (just as you are doing it via getCallerPrincipal()).
We also place the users identity in a thread local variable, so that classes down the call chain from the EJB do not have to be "container aware". They simply access the identity from the thread local and use the security classes to look up user profile information. This also makes it easy to change the implementation for testing, or even something other than LDAP lookups.
Other conveniences we created were a JDBCServiceLocator that retrieves connections with user/password for the current user. So the developer does not have to explicitly code the security lookups at all.
Normally the Java EE security model will not allow the retrieval of the user password, for security reasons. But it depends on the implementation. Some vendors provide methods to retrieve this kind of information, but if you rely on such implementations, be aware that the portability of the application will be compromised.
One common approach is to write a servlet filter to intercept the login request and save a copy of the credentials, to be used later. If your application doesn't use the Java EE security infrastructure, this could be easily implemented. That's because some vendors prevent you from filtering an authentication servlet.
Robin,
Sounds like what I was planning. I figured I'd make a call right after a successful server connection to load the credentials into a threadLocal variable on my connection class. I was hoping there was an easier way - but I guess not.