How to setting a session variable AFTER sending the response? - java

Is there a way to set a session variable AFTER the response has been delivered?
I want to avoid that any filter will see this change in the current request.
To clarify the context I will talk about the use case.
My task is to adapt a complex Java EE application (Spring, acegi, struts, JSP, Apache Tiles, aso) to user needs.
Users could login to this application.
If a user account is used a second time, the new session should warn that continuing will invalidate the original session.
Any request after presenting the warning (due to clicking a link) should invalidate the original session.
One problem is, that currently setting session variable were visible to other (spring) filters.

You can create a filter which is the first in the filter chain. This filter will be called last when the request is postprocessed. And you can set the session variable when the filter is called the second time.

If you have a session, you can keep a variable only server-side. Keeping it in a session bean would be the normal procedure. Quite simple.

Related

How to invalidate other session in java servlet [duplicate]

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.

What happens with the spring controller #SessionAttribute when session get timeout

I have a session attribute in my controller #SessionAttribute("sample_dto"). I need to work with the sample_dto even after session get timeout. What is the way to do this properly.
PS: When session get timeout, browser is redirected to login screen. How can I avoid it and bring it back to the place where I was before session get timeout.
Thanks
According to your question, I think you don't need a session attribute. Because you need to access the same data item in between
separate sessions. The simplest solution is to use a normal instance variable. Because your controller is singleton in default.
It is similar to application scope since you don't change the scope of your controller and don't restart your application.
If this task is user specific (your data item should persist per user basis), then you can use cookies for saving the temporary user status.
In order to set the cookies you can implement your own HttpSessionListener class and within the sessionDestroyed method you can do your cookie saving things.
Because you need to do this thing only when your session is get destroyed(timeout).
If your data is much bigger, then you can save the data in the database by referring to the relevant user. You can use the same sessionDestroyed method.

Glassfish 3.X, programmatically handle the termination of arbitrary HTTPSession

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.

How to update multiple sessions based on an Event

In our web application (in JBoss using Struts) we use sessions largely for security as well as to cache some data for a User. Thus, every user logged into the application has a session and different data cached in it.
Based on some parameter change, i want to change the cache of the subset of users who are logged in (i.e. have session)
Can this be achieved? I have not been able to find anything so far from general search.
You can use a HttpAttributeListener
a basic example here
HttpSessionAttributeListener:
The HttpSessionAttributeListener interface enables an object to
monitor changes to the attribute lists of sessions within a given Web
application. The HttpSessionAttributeListener in turn extends
java.util.EventListener. The methods in it are
attributeAdded(HttpSessionBindingEvent se)- This is the notification that an attribute has been added to a session.
attributeRemoved(HttpSessionBindingEvent se)- This is the notification that an attribute has been removed from a session.
attributeReplaced(HttpSessionBindingEvent se)- This is the notification that an attribute has been replaced in a session.
You can do it by storing each session object in a static List<Session> in some holder object. You can put it by a HttpSessionListener#sessionCreated(..). Remember to remove it from the list on sessionDestroyed(..)
Then, whenever you want to do something, simply loop the previously stored list of sessions and do whatever you want with them.
You have basically 2 options:
Push the changes. Get hold of all HttpSession instances in an application wide map which you manage with help of a HttpSessionListener. This way you can just get them from the application scope and walk through them to make the necessary changes directly.
Poll the changes. Store a change instruction in the application scope. On every HTTP request, check with help of a Filter or ServletRequestListener if a change is required, then make the necessary change in the current session and remove/disable the change instruction.
A completely different alternative is to use an application wide shared cache, such as Terracotta or Ehcache, so that you don't need to duplicate the same data over all HTTP sessions. You'd just need to deal with the data on a per-request basis. When database access comes into picture with JPA, then read on about "2nd level cache", that's exactly what it does.

"remember me" functionality with jsf 2.0

I am trying to implement "remember me"/"autologin" functionality. I have stored a cookie at the client but when should I read it? If I try to do that in a filter, for example, I won't have access to my application-scoped beans which I use to access the db.
What are the best practices to do that?
It depends a little on how your current login exactly works. Is it a container login followed by custom stuff (like putting some object in the session) or only custom?
In the first case you can't do an auto-login completely in JSF, since the container will kick-in whenever the uses tries to access a protected resource. In that case you still need to do the container login part in a Filter (HttpServletRequest#login).
For both the first and second case, the JSF part can be done via a global PhaseListener. In this case you could listen to a very early event, e.g. before RESTORE_VIEW. In this event handler, you can check the session for whatever object your put in there to flag your login, and if it's not there use the HttpServletRequest to check if there's a "remember me" cookie and proceed with the login if needed. When the PhaseListener is called, JSF is fully operational and you can access your application scoped managed beans.
If you only use an object in the session and don't bother doing any container login, then you can simply skip the first part.
p.s.
Another option is not to put any DB stuff in JSF managed beans, so you don't need JSF operational in order to access your DB. In a Java EE application, EJB beans are alternative candidates (and actually better suited for this job). They can be injected into your filter and used to access the DB before the JSF life-cycle starts. Next to EJB beans, CDI beans are also an option. In many ways, these are better alternatives for JSF managed beans anyway.
Session scope will keep content for as long as a session is active, combine it with a state persistence either in DB or via a cookie.
Non of the scopes will really "remember" your state by itself, the best you can do is persist the state to the DB and when the user returns, restore it as best as possible and push the data into a sessionscoped bean.
Otherwise extend the sessionscope's session via a cookie
FacesContext.getCurrentInstance().getExternalContext.addResponseCookie(..)

Categories