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.
Related
The issue
I'm working on an application, which, as many applications, starts with a login page before showing any kind of data.
The problem is that my client specifically requested that the credentials entered should be used to access the database.
This means that, instead of running the username / password against a "user" table, they will be used to acquire the user's database personal access.
It was decided by my superiors that this application would be build on top of a SpringBoot skeleton, which happens to be using a Stateless JWT Authentication mechanism.
I'm no expert when it comes to comparing the benefits of Stateless vs Stateful, but if I understood the concept correctly, this means that my application will need to re-establish the database connection with every single request, right?
I'm asking this because we are experiencing very slow response times.
The code seems to hang a little while on database setup related code, such as
dataSrc.getConnection();
or
entityManagerFactoryBean.afterPropertiesSet();
A possible solution?
I've heard of Hibernate's StatelessSession, but I was unsuccessful in setting it up.
I'm not even sure it would help at all, but from what I read, it uses a lower level Hibernate API, which might help mitigate the problem, without much of an impact on the way things are already coded since the SQL operations are exclusively stored procedure calls, which are manually mapped to Java objects.
What I need help with
Basically, I just want answers to 3 questions :
Question 1 :
Should I simply revert to Stateful authentication, because Stateless models are unadapted to my use case scenario?
Question 2 & 3 :
Can StatelessSession system even be implemented in my scenario, and would it make a significant difference on the database connection time?
But, of course, if you know of any other lead that my help me solve my problem without having to revert the whole thing to Stateful, I'm taking it!
Finally got time to answer this (in case someone passes by in the future).
Basically, I had two choices : remove Hibernate altogether or "go back" to Stateful sessions.
I went with the first option, wich I could do only because we had no annotation based mapping between our java objects and our database.
Going Stateful might have been a better approach, but i didn't really know how to do that. I found an impressive amount of articles underlining how to go Stateless, but not how to go back Stateful and... Well... Doing it backward wouldn't be enough, since I would be missing a lot of configuration, so I'd have to research it, and it was a hassle I had no time to deal with.
Using a custom implementation of org.springframework.web.filter.GenericFilterBean, I wrap every incoming request in a custom requestWrapper containing the database connection.
I open / create said connection using the java (low) API : java.sql.DriverManager.getConnection
I can then retreive this connection from my wrapper, wich is vehiculated through the application by Spring by using this code :
ServletRequestAttributes att = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
ContentCachingRequestWrapper springWrapper = (ContentCachingRequestWrapper) att.getRequest();
CustomWrapper myWrapper = (CustomWrapper) springWrapper.getRequest();
myWrapper.getConnection();
Just don't forget to properly close everything to avoid memory leak and you're set.
One would also need to register the driver properly, just by calling the constructor of said Driver in the application main class.
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.
I was writing j2ee code but i am facing a problem with session attribute.
Regarding ensuring of thread safety for session attributes which is being set and accessed in a servlet?
As, i know we can not implement "SingleThreadModel" because this is deprecated in java and also we can not synchronize the doXXXX() method.
I tried to use "SingleThreadModel" but it did not work.
Then How can i ensure it?
Can i synchronize the session object for the same?
please tell me, how to fix it.
You need a session scoped mutex. I.e. synchronize on the session, or better a use case specific object in the session.
You should keep the scope of the mutex as small as possible, as you might result in serializing your requests. I tried it once on a project of mine, where I used Spring's RequestMappingHandlerAdapter.setSynchronizeOnSession() which simply synchronizes on the session for each request. This had a significant impact on a page which displays a list of rendered images. I could watch appearing those images sequentially.
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.
In the Java Servlet API, what is done to ensure that someone's session id is not stolen?
For example, if I had an active session and someone somehow get a hold of my session id, could they use it?
Nothing prevents it. You get the session ID, you can take part in the session.
In the usual case of cookies this is not a risk in itself. The attacker should not be able to read a user's session cookie unless:
they've got man-in-the-middle capability, in which case you've got much worse problems than just session IDs;
you've left a cross-site-scripting hole, in which case you've got much worse problems than just session IDs;
you're vulnerable to DNS-rebinding/cross-domain-cooking attacks, in which case you should fix it by only allowing known-good Host: requests.
(Whilst you can try tying sessions to IP addresses, this risks breaking valid sessions due to eg round-robin proxies. IPs can be used as part of a wider strategy for detecting suspicious activity, but on the public internet it's not a good idea always to require each request in a session to come from the same IP.)
Unfortunately in Servlet there is another case, apart from cookies: jsessionid= parameters. Since they appear in the URL itself, that makes them much more leaky (eg via referrers and pasted links). And that's far from the only practical problem with parameter session IDs. They mess up navigation and wreck SEO.
In my opinion jsessionid= URLs are one of Servlet's worst early mistakes, a discredited cookie fallback strategy from yesteryear that shouldn't be used for anything. But certainly they shouldn't be allowed to grant access to any privileged data; consider using HTTP Basic Authentication instead if you need a fallback mechanism for browsers that don't support cookies.
In Servlet 3.0 you can disable jsessionid= URLs easily using <session-config> in the web.xml; unfortunately in previous versions you are left mucking around with filters if you want to properly disable the feature.
Yes, they could use it. Nothing is done to protect it unless you put all your traffic over SSL.
This is how Firesheep works, which recently got a lot of attention for making session stealing easy.
Yes, the Session ID gives someone access to the corresponding session.
You could store the IP used during login in the session and when the IP changes require the user to login again.
Additionally (not sure if that's done automatically though) you could do the same for the User Agent - not really increasing safety against malicious attacks though, just against dumb users giving away their sessionid accidentally if it's passed via GET and not a cookie.