There is a task of managing desktop client session status:
Ensure only single client is "connected".
Force client logout - kill session.
Kill client session on timeout due to inactivity.
Server-side is JBoss and EJB3. How to achieve such task?
You can use Singleton Pattern here, once initialized, deny subsequent requests thereafter in synchronized method by using delegate to access interfaces (local/remote).
Maintain you own idle-timer & start it at event occurence either mouse/key for your window.
On timeout, you can de-reference the initialized objects & redirect to login.
Method annotated with #Remove allows to kill EJB3 session.
We can ensure uniqueness of session by adding it to static (or other unique) container and check for existence before returning it for the new client. If existing session found, we throw an exception for the user.
So, this answers my questions, I think.
Related
What's the difference between ManagedSessionContext and ThreadLocalSessionContext both has a ThreadLocal in their implementation for maintaining sessions
ThreadLocalSessionContext - It takes care of the hibernate session management activities like :
Creating a session if one doesn't already exist.
Binding the session to the ThreadLocal, so that sessionFactory.getCurrentSession() returns this bound session and unbinds it once the transaction is completed.
Flush and close the session at the end of transaction complete.
ManagedSessionContext - Responsibility of session management activities like above are handled by some external entity (generally some form of interceptor, etc).
In both the cases the session is stored in the ThreadLocal though.
But the call to bind/unbind of the session and especially when to call flush and close on the session are defined via the external entity.
This gives more flexibility, for example, in the case of ThreadLocalSessionContext, the session is closed automatically when the transaction ends and it is not possible to leave the session open for multi-request conversation type of requirements.
In case of ManagedSessionContext, we can implement multi-request conversation (a.k.a session-per-conversation model) the same session needs to be kept open and should be reused across the user requests. So in the first user request we insert/update/delete some entities and in the next request we do some more operations and finally at the end of third interaction we want to commit the data.
Quoting from Managing the current Session section
When a conversation starts, a new Session must be opened and bound with ManagedSessionContext.bind() to serve the first request in the conversation. You also have to set FlushMode.MANUAL on that new Session, because you don’t want any persistence context synchronization to occur behind your back.
All data-access code that now calls sessionFactory.getCurrentSession() receives the Session you bound.
When a request in the conversation completes, you need to call Managed-SessionContext.unbind() and store the now disconnected Session somewhere until the next request in the conversation is made. Or, if this was the last request in the conversation, you need to flush and close the Session.
To represent that pictorially,
Session scoping with ThreadLocalSessionContext
Session scoping implemented for Session-per-conversation using ManagedSessionContext
You can go through the Listing 11.5 of this link for a sample implementation an interceptor that manages the session for session-per-conversation model.
I have a web app that uses a Java Bean for login functions right now and all of the JSP pages check the Bean to make sure the user is logged in. I am also introducing some AJAX functionality now with servlets and I see that of course those exchanges don't check authentication. I'm wondering how I should handle this. For example, I don't want someone to be able to logout, hit back button, then submit something with the AJAX functions successfully.
I can't access the bean from the servlet to check the login (totally wrong context and static vs non-static). I guess I could set a flag with the user entry in the database table denoting logged in or not. Then I can detect timeout logoffs and update the flag as well. But that way would require extra database accesses every time something is done. It would duplicate functionality in some way, but I guess I could perhaps use that just for the AJAX stuff. One difference with that would be the user would not be able to be logged in on multiple places at once as currently.
How is this kind of thing normally done?
Thanks for any help!
You could use session to store that flag instead of the database, and when the user logs out you should remove that flag and destroy the session. In login method
HttpSession session = req.getSession(true);
session.setAttribute("loggedIn",true)
And in your AJAX code
if(eq.getSession(true).getAttribute("loggedIn")==true)
doWork();
else
error("not logged in");
The webcontainer will handle timeouts for you, keep track of each user and his session, and so on.
But I would recommend that you use a standard for managing authntication
This is not a simple question its just because i'm rethinking our architecture for securing our EJB 3.0 service by a login and security.
We have a EJB3.0 application on JBoss 5.1 that offers various services to a SWT client to read and write data. To use a service, the client must login with a valid user and password which is looked up by SpringSecurity in a LDAP server. SpringSecurity generates a session id which is passed back to the client to be resused in any further service call.
client server
| |
|-> login(user/password)-------->|
| |
| <------- sessionId ------------|
| |
|-->serviceXy(sessionId,param1)->|
The situation seems clear. We store the sessionId in our own context object which is the first parameter of each service method. There is an interceptor on each service method which reads the sessionId from the given context object and checks if the session is still valid. The client needs to call the login service first to get a context object filled with the sessionId and reusue this context object in further service calls.
public class OurContext {
private String sessionId;
}
#Stateless
#Interceptors(SecurityInterceptor.class)
public OurServiceImpl implements OurService {
public void doSomething(OurContext context, String param1) {
[...]
}
}
The thing i don't like at this solution is the polution of each service method with the context parameter.
Isn't there a similar mechanism like a http session in rmi calls? I'm thinking of putting our context object in some kind of session that is created in the client(?) right after the login and is passed to the server on each service call so that the SecurityInterceptor can read the sessionId from this "magic context".
Something like this:
OurContext ctx = service.login("user","password");
Magical(Jboss)Session.put("securContext", ctx);
service.doSomething("just the string param");
Since you are already using an app server, it seems that you should be using the built-in EJB security mechanisms, generally provided through JAAS. On the 4.x jboss line, if you implemented your own JAAS plugin for jboss, you could get access to a "special" context map (similar to what you describe) which is passed along on remote requests (by the jboss remote invocation framework). I haven't used jboss in a while, so not sure how this maps to the 5.1 product, but i have to imagine it has similar facilities. This assumes, of course, that you are willing to implement something jboss specific.
There are some kinds of session mechanisms in EJB, but they all start when the remote call starts, and ends when that ends. On old one is the transaction context ( Adam Bien wrote about this some time ago), and a newer one the CDI Session Scope.
Contrary to popular belief, this scope doesn't just mirror the http session scope, but in absence of an http session (like for remote calls), it represents a single call chain or message delivery (for mdbs).
With such a session, your remote SWT client still has to pass the sessionId to the remote service, but any local beans called from there can pick it up from this "cdi" session.
The other option is kinda like what jtahlborn says: with your own login module you can return a custom principal, instead of the default one. Your code can first request the normal principal and then try to cast it.
The problem is that this stuff is container specific and JBoss always forgets about it. It pretty much breaks after every update, and users have to kick and scream to get it fixed in some next version (only to see it break again in the version after that). Without JBoss really supporting this it's an endless battle.
Yet another option is to let the user login with the sessionId as name. The login module behind that could be a simple module that accepts everything and just puts a principal in the security context with the sessionId as 'name'. It's a little weird, but we've used this succesfully to get any data that can be expressed by a string into the security context. Of course, you would need to let your client do a regular container authentication here, which kinda defeats using Spring security in the first place.
We went for another approach which is portable and does not rely on a specific app server. In addition our security implementation frees us from the restrictions of the EJB approach (which by the way I thought were closed 2 decades ago ... but came up again).
Looking top down:
There is a server providing classes with methods to work on same data.
The client(s) provide the data and invoke specific methods.
Our approach is to put all data (and therefore communication between client and server) into a "Business Object". Every BO extends a superclass. This superclass contains a session id. The login method provides and returns that id. Every client only has to ensure to copy the id received in one BO into the next one it sends to the server. Every method which can be remotely (or locally) invoked, first obtains the session object with the received id. The method to return the session object also checks security constraints (which are based on permissions and not on roles like in the EKB approach).
A new corporate policy on Secure Coding was recently put into effect. The initial audit assessment tagged me deficient for:
Session state must be managed such that a session will withstand replay-attacks.
I'm not exactly sure what this statement means or why I am defecient in it. I'm developing a Java Web application and set a session as such:
session.setMaxInactiveInterval(36000);
Session state must be managed such that a session will withstand replay-attacks.
The statement is way too confusing. Rewording it would yield:
The session management framework must protect the application against replay of session IDs.
It is less confusing (hopefully), and continues to carry the same meaning as the former (again, hopefully).
Typically, if one were to implement a home-grown session management framework instead of relying on the one provided by the container for instance, then it is quite possible that the session management feature of the application would be susceptible to a replay attack.
A session replay attack would involve the scenario where the session ID is replayed back in a request, after the session has expired. A well written session management framework would recognize that the provided session ID is not a valid session ID. However, there have been instances where a vulnerable session management framework accepted the now-expired session ID, and recreated the contents of the session. In worser scenarios, the session management framework did not destroy the session at all, on session expiry, resulting in the scenario where a session ID replay resulting in requests being processed.
It must be remembered that even normal users of the application may unintentionally perform session-replay attacks, if they are able to browse to protected pages in the application without logging in. This is an indication of a failure in the authentication and the session management features of the application, for the app should ideally allow users to browse protected pages only after successful authentication, which would yield a token (a session ID) that may be used for a certain duration to access the site without further authentication. If you are using persistent cookies for authentication, you may have unintentionally introduced a hole.
Going by the above, one can protect any application from session replay attacks by:
Ensure that you are using the container provided session management features. From the use of the session.setMaxInactiveInterval I would assume that you are it. But, to be sure, verify if you are creating session IDs using other means, or for that matter, verify if you are using identifiers that are equivalent to session IDs. In simpler words, ensure that your application relies only on the value of the JSESSIONID cookie (or the equivalent as configured in the container) to communicate session IDs to the browser. Also, verify if persistent cookie are in use (refer the above posted scenario).
Invalidate the session after a certain idle period. If you do not invalidate the session, then an attacker has a larger time window to brute force the session ID. From the point of view of session-replay attacks, this is worse since the attacker can replay back a compromised session ID at any point in time, and still get access to a valid user session. You would also want to revisit the duration specified in the session.setMaxInactiveInterval for the value you are using currently is 10 hours. I would consider that to be insecure. Most applications do not require a rolling window of session expiry beyond 30 minutes, with 10 minutes being the value recommended for high-value apps.
Destroy the server-side session and it's contents on expiry. In a servlet container, this is typically done by invoking session.invalidate() in a logout page/link. Ensure that you have provided users with a link to logout from the application in the first place, so that the logout request can be processed to invalidate the session using the before-mentioned API call. If you do not perform this activity, the server-side session object will be destroyed only on session expiry (which will occur after 10 hours of inactivity by the user; now you see why 10 hours is a bad idea).
this is to do with something similar to session hijacking.. where the auth token is held by a hacker to login at a later stage..
in my projects i've added a simple filter which does the following.
every jsp page which is responded would be given an attribute called id (the token is generated using UUID().. the same token is placed in the session..
when a page is posted, the filter (which is configured to filter all requests) checks for the equality of these tokens & proceeds only if the values match.
we also added a timestamp in the session & the database, whenever a page is submitted we check the time stamps in the session with the db.. if the number is within 10 ms then the request passes, else the user is redirected...
This question already has answers here:
How to call sessionDestroyed when a session times out
(5 answers)
Closed 5 years ago.
I have an implementation of HttpSessionListener where 'locked' resources in the application are released with sessionDestroyed method.
The 'lock' information is maintained in database, and the release of locks is working fine in most cases. But In some cases I still see resource is locked - even if there is no session active!
So, I'm doubting if there is possibility that sessionDestroyed not being invoked? Suppose if the session is timed out - will sessionDestroyed method be called?
Suppose user closes browser tab without logging out(destroying session) -then will the listener be invoked?
Thanks in advance!
A servlet engine will handle session timeouts.
It will determine on its own when the session is no longer valid and it will call the sessionDestroyed. (this can occur some time after the user closed his browser).
Some other points :
Logging
Perhaps you can add some logging to sessionCreated and sessionDestroyed methods. for each sessionCreated you should have a sessionDestroyed.
Excepion Handling
Perhaps the fact that stuff remains locked is not due to the session not being destroyed, but perhaps due to an error in your sessionDestroyed logic. Do you have sufficient exception handling / logging in place there ?
Timing
Did you wait long enough to check your locked resources ? (close all clients, and take into account the session timeout value configured on the application / server). As stated earlier, the server cannot detect a user closing a browser, but it does maintain its list of http sessions, and it will destroy them after timeout.
So, I'm doubting if there is possibility that sessionDestroyed not being invoked? Suppose if the session is timed out - will sessionDestroyed method be called?
Yes. A session is destroyed when it times out or someone expires it programatically (via HttpSession.invalidate()).
Suppose user closes browser tab without logging out(destroying session) -then will the listener be invoked?
No, because the session is still valid. If said user opens up the website once again, his/her session will still be valid.
From the HttpSessionjavadoc:
Notifications are sent after the binding methods complete. For session that are invalidated or expire, notifications are sent after the session has been invalidated or expired.