Consider the following scenario.
I've a Java EE web application (JSF 2.2, JPA, EJB 3.0 even if the framework doesn't matter here) deployed on Glassfish 3.1.1 with a login protected area, which I'm protecting through the standard Glassfish security mechanisms.
My business model is based on selling access to this web application as a service, forbidding multiple logins at the same time for a single username/password. For this reason I'm keeping a column in my database that I increment upon user login and I decrement upon user logout. Additionally, I've a method in a SessionScoped managed bean annotated with #PreDestroy that takes care of decrementing the counter when the session expires (60 minutes configured in the web.xml via the session-timeout attribute).
When the user try to login with a counter greater than 1, the application notifies him about the issue, inviting him to logut the previous workstation first.
This is working quite well, but we are having an incrementing amount of users that perform their actions, close the browser (without loggin out), and then try to authenticate from a different workstation within the session timeout limit (which, again, we've set to 60 min).
In these cases we would like to be able to offer the opportunity of closing all the previous sessions associated to the user login directly from the new workstation (so an user X, logged with his own session, should be able to ask the termination of different sessions logically linked to its account). I'm aware that if he/she just waits 60 min the session will be eventually terminated by Glassfish but we would like to avoid the support requests coming from this "issue" (you know it's hard to explain this kind of stuff to non-technical users).
My first plan would be to store the jsession ID of the user HTTPSession somewhere, to access the old sessions (if any) via the stored jsession ID and to close or invalidate them on demand. I've read a lot of material on the subject, and I found this SO question with apparently the answer I'm looking for (a method of storing the HTTPSession in a map using the jsessionID as key to get them back). It seems pretty simple and I could implement that in a matter of minutes, BUT the comments below, especially the second part of the answer coming from #BalusC is driving me to ask your opinion on how I should implement this in a safe way.
It's a matter of best practice, how would you guys implement this?
I don't need code, just your opinion as Java EE architects or a reference of some sort of documentation on the topic.
Keep track of all logins in DB (you can use HttpSessionListener to remove entry when session get destroyed). Make sure that you've a boolean column "should kill session now!" in DB which defaults to false. When the action is given to kill all other sessions now, set the boolean to true for those sessions. In a filter, on every request, check the boolean value in DB and handle accordingly.
This way you don't need to have a handle of all physical HttpSession instances.
Related
We are using Angular5 as front-end. Spring Boot JAVA for APIs. We would like to maintain logged in/logged out details of users like, when a user say user1 logged in(field loggedin in table is set as 1), and after logout (loggedin field value updating as 0).
This is working fine in normal scenario. In case, user closes the browser or closes the tab, at that time, API is not triggered so consequently, in table level also it is not updating.
Finally, we thought like, if no APIs are triggered for certain 5 minutes or certain time interval then we have planned to assume the user might logged out. So, we are trying to find out , like if no APIs are calling for last 5 minutes user-wise. How can we arrive it?
Actually, we are new to Spring Boot JAVA. Kindly guide us on this or any other idea or suggestions are greatly appreciated.
Thanks in advance.
I think you are using extra tags to track user activity, maybe you want to limit it to users current actions (like for logout, just update that logged out, as it would implicitly mean used not logged in anymore).
To achieve what you are looking, there is a session associated with every request, maybe new created or the existing one. You can keep a track of sessions created, and if any session is inactive for more than timeout time, you can destroy the session and while doing so, you can update the status of related tags at that step.
Okay. What I want to do is be able to, when I update a user, invalidate any session that they currently have in order to force a refresh of credentials. I don't care about being able to directly access the session-specific user data. Ideally, I would also be able to restrict users to one session by a similar manner.
What I tried doing is creating a HashMap using the username as key and HttpSession as the value (my actual setup is a little more involved, but after repeated seemingly inexplicable failures, I boiled it down to this simple test). However, whenever I attempt to tell the retrieved HttpSession to invalidate, it seems to be invalidating the current [admin] session. Is HttpSession inextricably bound to the current request?
Or is there an entirely different way to deal with this?
If it happens to matter, I'm using Jetty 6.1.26.
There's no straight forward way. The easiest way I can think of is to keep a flag on the database (or a cahche) and check it's validity on each request.
Or you can implement a HTTP Session listener and keep a HashMap of user sessions that can be accessed and invalidated.
I haven't tried any of these out so I don't know of any performance issues. But it should be acceptable for most applications.
Well, as far as I can tell, there's no way around it. Using a request-scoped bean didn't work as I expected (although it did give me good insights into how Spring operates, intercepting field accesses). I ended up using a dirty flag on my SessionHandler (a session-scoped bean) with a very high-priority aspect checking and, if necessary, calling invalidate() on the session in the user's next request. I still ended up having all my SessionHandlers register with a SessionManager, and a #PreDestroy method to unregister them in order to avoid a bunch of null entries in the map.
When a user is interacting with a website, there's usually some object that could be considered the "current" object, like a shopping cart, or, to use an example in my world, a manufacturing job. What's the best practice for tracking that current object from page to page? I can think of a few:
put the ID as a request parameter (downside is security, since a
hacker could use that to change the URL to a different ID)
a session object (downside is if you have a huge amount of users
and/or the current object has a large memory footprint)
cookie? (Haven't tried that one)
Have I missed some obvious answer?
BTW, we're using Java, WebLogic and Struts1.
It really depends on your technology stack as to what "best practice" would be for you right now.
For example, if you're building a traditional Rails application using ERB templates without a MVC front end or anything, then I think that using the session object that the Rails framework provides for you would be best.
Most web frameworks will supply you an easy way to keep track of a particular user that's browsing the website. Most of the ones I've seen use a combination of your second and third options. They have a session ID that is stored as a cookie in the user's browser and every time that user sends a request to the web server, it loads a Session object from memory or the database using the session ID value that was stored in that cookie. Memory shouldn't be an issue unless you have an enormous number of users, but that also depends on the type of information that you're storing in there.
If you're storing entire database rows or records, and the sessions are being stored totally in memory, then maybe you should consider only storing the IDs to those records.
Research your particular web framework well to see how it handles user sessions.
As far as a cross-platform best practice, the Session object paradigm seems tot be the best approach to date. It permits matching of request parameters to tracking of sessions independent of the handling of the request parameter. An extension to this is that the Session object provides a handy place to put a collection of things for use if the session is re-identified (Java uses a Map).
Generally the Session is a representation of a single web browser visiting a single website repeatedly. Since there is nothing associating one request to another, this is generated synthetically from a combination of items, including user agent string, reply ip address, etc (in the past it was a stored value in a cookie, which caused no end to security issues).
Assuming you have a reliable Session object available, typically one stores the items that a supposed "single user" driving the session should have access to. So, if you have a shopping cart, it might be represented as a shopping cart object accessible from the session. In Java, that might be a map.
When identifying a new session
// request is a HttpServletRequest object in this example
if (request.getSession(false)) {
// must be a new one
Session newSession = request.getSession(true);
newSession.putValue("shoppingCart", new ShoppingCart());
}
Later on, when adding to the cart
ShoppingCart cart = (ShoppingCart)(request.getSession(false).getValue("shoppingCart"));
cart.addItem(item);
The benefits of separating out the detection from the request handling make it easy to fix / tweak session tracking without altering the code for the "session contents".
The other Answers are correct. Just a bit more explanation.
The Java Servlet technology’s Session object is indeed aimed at solving this exact problem, how to track a single user’s set of current objects over time, beyond the HTTP request-response lifecycle. This lends statefulness to an otherwise stateless protocol (HTTP). Every Servlet container (Tomcat, Jetty, WildFly, and so on) automatically handles the details such as using cookies or URL rewriting so you needn't worry about that.
Yes, as you add stuff to the Session object its memory usage grows in size. If running low on memory, your Servlet container such as Tomcat may choose to write an older Session object to storage using Serialization. The catch here is that all your objects in the Session must be serializable. Ensuring your classes (and all their nested objects) can correctly handle serialization can be a big chore.
Tip: If possible add memory to your server to more that handle your highest session load. As the wise man said, "Algorithms are for people who don’t know how to buy RAM.".
I am trying to learn more about JAVA web development. I am mainly focused on trying to understand how data that a user enters, maybe through the course of filling out a multipage form, is managed as the user moves from page to page.
From what I have gathered, you can store data within the session on the server side. I am also learning about cookies which are stored within the browser. Is there a general rule that is used to determine what data should be stored in a cookie vs. when you should store data in a session (session.setAttribute), or are these completely different concepts?
Thanks
The basics of session/cookies are like this.
A session is typically a way for a server to store data about a user. This can be done in a variety of ways from memory, file to database. This session can be used by you store pretty much anything you need to have as the user bounces around your site. It is assigned an ID (the session ID) which you don't usually need to worry about too much. In most web languages you can easily access the user session with some functions without dealing with IDs.
Now since the web is stateless - meaning there is really no way to know that user that visited page A is the same as the one that visited page B then we want to make sure that the user carries their session IDs with them. This can be done in a variety of ways but the most common one is through the use of a session cookie which is a special cookie automatically set by the server that is solely there for passing the session around. It can also be passed in the URL (I'm sure you've seen things like index.php?sessid=01223..) as well as headers and so on.
When most people talk about adding info to a cookie they are not talking about session cookies but about a custom cookie that you specifically set. The only reason that you would want to do that is if you needed to store info beyond the life of the session (which ends when the browser is closed). A good example of that is the "remember me" feature of many sites.
So use sessions unless you need to have something last a long time.
Yes. There are a few rules actually. For one, cookie data is sent by the browser on every request; session data is kept on the server (and not re-transmitted every request). However, usually the session id is used with a coookie. This enables the server to identify the client.
I've been always trying to avoid using Sessions. I've used spring security or other ways of having user logged in the application, which is I suppose the major use case for using Sessions.
But what are the other use cases ? Could you please make a list of those most important ones ? How come that I've been able to develop even complicated applications without using Sessions?
Is it because I'm using spring-mvc and using Sessions is practically not needed except the login stuff ?
EDIT: Guys this question was asking for use cases... Most of the answers explains what are sessions for. If we summarize some usecases, we can say for sure, when to use database or sessions for maintaining conversation state...
Don't you remember any concrete scenarios you needed sessions for? For past years :)
for instance some conversational state may become persistent after some point / event. In this case I'm using database from the beginning.
I think you can do anything you want without storing anything on a sessions.
I usually use the sessions to avoid having to pass state between the client and server (used id as an example) and when I don't want to send sensitive information to the client (even in encrypted form) as it might be a security problem.
Other ways of avoiding using the session are:
store some state on a database, e.g. shopping carts, instead of in the session, even if the cart is discarded after a certain amount of time.
store state in cookies e.g. for user customization
One use case when it's really useful to use the session is for conversations, although usually frameworks manage that behind scenes, and store the conversation in the session.
edit
Converstions (in my understanding) are something like wizards, in which you complete several forms in different pages and at the end you perform the action. e.g. in a checkout process, the user enters his name, shipping address and credit card details in different pages, but you want to submit the order just at the end, without storing any intermediate state in your DB.
By sensitive information I mean, imagine in the previous example, once the user sent his credit card details, you shouldn't return that information in any format (even encrypted) to the user. I know it's a bit paranoid, but that's security :).
In the ecommerce system i'm working on, there is an external system at the back-end which stores users' saved shipping and billing addresses. Our web app talks to it by making web service calls to retrieve those addresses. When we get the addresses, we store them in the session. That way, we only have to call the service once, when the user firsts looks at their addresses, and not every time we serve a page which needs address information. We have a time-to-live on the addresses, so if the addresses change (eg if the user telephones the customer service desk to change an address), we will eventually pick up the fresh ones.
It would be possible to store the addresses in our database, rather than in the session. But why would we? It's transient information which is already stored permanently somewhere else. The session is the ideal place for it.
Well in one sense your question is deep (what's SPECIAL about a session is worth knowing) and in another sense it's shallow (what can't I do if I don't use them turns out to be a somewhat odd question)
In the end a Session is merely (or could be) a ConcurrentHashMap (in fact it usually isn't that threadsafe) with a a key of unique session id passing as the cookie. You know why it's useful, but to answer you for use cases
clustering (this is how state gets distributed across nodes)
caching general state of the user and their objects (as opposed to reloading from db each time)
built in methods for sessionlisteners to watch when someone is timed out, or attributes change.
= used for by a lot of localization utilities
Can you do all this with a database or your own hashmap implementation/filter? Of course, there's nothing magical about Sessions. They are merely a convenient standard for having some objects follow a logged in user and be tied to the lifetime of that user's use of the application.
Why do you use Servlets? You could also implement your own socket level standard? The answer to that is using standard apis/implementations provides convenience and other libraries build upon them.
The cons are
you are reinventing the wheel and some code that has been time tested
you won't be able to use a lot of built in facilities for monitoring/managing/clustering/localizing etc.
Sessions are one way of maintaining conversational state across multiple requests (e.g. multiple stateless HTTP requests.)
There are other ways of implementing conversational state, for example, storing an authentication token or some suitable conversation id as a cookie and maintaining a store of conversation id to session state. (In essence, duplicating what the app server is doing when it provides sessions.)
That you haven't needed to use sessions means that your application either doesn't need conversational state or you've implemented it in a different way. For example, perhaps your application uses an authentication token (say a cookie) and persists all state changes to the database. With that kind of arrangement, there is no need for a conversation state.
Hi you can take an example of shopping cart because since Http is stateless protocol it does not maintain the status of the user who sends the request.
For e.g.
If one user sends a request to buy camera from say eBay and after some minutes another user sends a request to buy laptop.
But since http is stateless protocol so server is not able to separate the request send by the users and may it happen that the bill of the laptop may be given to first user.
So through session we can maintain a particular entity over the server side for a particular user.