Most servlet containers seem to store HttpSession data in-memory. I wonder if this might cause a problem if, say, 500 users are logged into a servlet-based web app at the same time. Let's assume I store two values per user, one boolean value isLoggedIn and one integer value userRole. Should I be worried about potential excessive memory consumption by the web app? Up to now, I've mostly done development in PHP where most frameworks let you save session data in an SQL DB.
Is there any realistic chance that in-memory storage might cause a problem? Maybe there is a formula to calculate RAM usage per active user session.
If your session data is large, yes you should worry about it. Tomcat has a persistence manager that lets idle sessions be paged out to a database.
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 am working on Spring 4 mvc application with mysql database, tomcat server.
Basically, I am creating a Spring rest which will be used by Angular JS.
Note: I am not using Spring security
In order to avoid session replication in case of clustered environment, I am using cookie approach.On login, I am generating one unique session id (using java UUID) and use it to create a cookie and then set the cookie in the response.Also, storing that session id in database along with any user data.
In order to authenticate every rest API, I have written a Spring interceptor which will intercept every rest API call which in turn check if there is a cookie in the request.If it is present, I am fetching session id value and using it, making a database call to check if it is valid or not. On logout, I am deleting the cookie.
Base on what i am doing as explained above, I have few questions:
1) Is my approach correct? or do you see any flaw in it.
2) Let me know if there is any other better method to achieve the same i.e. to avoid session replication.
3) Since, I am not using any HTTP session, how do I achieve something like session-timeout or do i even need it?
1) Is my approach correct? or do you see any flaw in it.
Its a good approach. Just a couple of points though in order of precedence:-
If you are using your API to service alot of requests then think about using in-memory cache rather then DB. Going to DB is relatively much more expensive. Alot is subjective I know and it depends on your setup, but just consider the DB for data you want to live beyond sessions. Better to use a more temporary/faster store such as an in-memory cache for things like API tokens. If across a cluster then explore a distributed cache solution.
Using cookies is not necessarily a security risk but have a bit of a read about CSRF. More secure to pass the token in a HTTP Header rather than in the cookie itself - that is if you are concerned about CSRF (I do use the Header approach in my own apps but I think CSRF is relatively rare and it depends on how sensitive your data is)
2) Let me know if there is any other better method to achieve the same
i.e. to avoid session replication.
Nothing to add over response to 1.)
3) Since, I am not using any HTTP session, how do I achieve something like session-timeout or do i even need it?
Store (preferably in cache) a timestamp with the token, and refresh it in the cache for each transaction that uses the token. Then, when checking if you consider if the token is valid, check the timestamp and you can decide (based on time elapsed) if you wish to remove the token and request the client to re-authenticate.
1 - Where session variables is stored in java web application ? on the client or the server side ?
2 - If i put a lot of objects and variables through the session it will slow down client's requests ?
P.S In my case i use spring mvc.
The "session" variable consists of two pieces, a very small session identifier which is stored on the client usually named jSessionId and stored as a cookie. But, the sessionId may also be encoded into URLs.
The second piece of a session is the actual data, and it is stored on the server. Possibly in a server-side database if the your server is part of a multi-server cluster. Each session is identified by that sessionId and the client sends it with every request. That is why it is designed to be very small.
Simple answer is : your session data are stored on the server side.
Web browser will get only an string id to identify it's session.
In fact, spring security takes more care of session information, because if users even don't login, session may not exist at all.
When I use spring mvc only, I don't use session to store important data, because session is stored in memory only. It is designed to save data temporarily.
When I use spring security, I have to save many important things in memory, such as account data which could not be transmitted on internet, and I won't load them from database every time. So I have to choose session.
So when the server which stored login session is down, all users have logged in on this server would have to relogin to retrieve another session id.
Session is not always the best choice, because when we have many servers that use session data, I have to share the data among all servers, anyway, net IO is expensive for servers.
1.it stored on server
2.Session stored on server ,so the Object you set in it may also stored on server.Request only send a SessionId to server to indentify this users Session to other users Session.
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