I'm refactoring an application which was doing its own session timeout management. I noted that the HttpSession supports setting a timeout value.
There is an event listener (HttpSessionListener I assume) that is redirecting to a 'timeout' page. "We're sorry your session expired, heres a link to the login page" kind of thing.
The problem is that when I first hit the app and am sitting on the login page, the session timeout event still fires. So I can be looking at the login page and get redirected to the timeout page.
What I want to happen is that if I am on the login page and only on the login page, that the session timeout does not occur. How do I do this?
I have already tried calling HttpSession.setMaxInactiveInterval(-1) in the default view resolution in the login's ActionBean, but that did not work.
I believe the session is being created, but not necessarily authenticated, whenever any page is accessed.
Where do you have the redirecting happening? If it's something declaratively set somewhere in a configuration file you could remove it and implement the HttpSessionListener interface.
In the sessionDestroyed method u would make the following:
Get the session from the sessionEvent
If the session contained an authentication flag then redirect
U could also keep the last page requested by the user and use that as a reference to determine whether to redirect or not but what do you do if a user is already authenticated and browses to the login page? I do not have a lot of information about your application.
Anyway the HttpSessionListener is the way to go I think.
Related
Wicket org.apache.wicket.authroles.authentication.AuthenticatedWebSession has 2 methods: signOut and invalidate. The javac says that signOut mark use not logged in while invalidate do the same (e.g. call signOut) but
remove the logon data from where ever they have been persisted
At first glace for logout action signOut should be called. But for security reasons session must be invalidated immediately after user logins or logouts. So from this point invalidate should be called.
So what to call for logout? Also when it is needed to call signOut and when invalidate?
If you want to logout only, use AuthenticatedWebSession#signOut().
AuthenticatedWebSession uses an internal boolean flag 'signedIn' to notice if a user has been signed in (true) or no body has been ever signed in or a user has been logged out.
WebSession#invalidate() is responsible for removing session from the Wicket session registry and its complete invalidation. The implementation of AuthenticatedWebSession#invalidate() invokes AuthenticatedWebSession#signOut() as well, so that the regular log out is done. That could be helpful if your logout process requires some other action, so you can override AuthenticatedWebSession#signOut() method.
In other words:
invalidate() calls signOut() and than removes the session from the session registry.
signOut() marks the session as 'not signed in', but it does NOT remove the session.
For logout you should use #invalidate()! In my opinion #signOut() should not be part of the API. At the best it should be an alias of #invalidate().
If you want to be really secure then you should use #replaceSession() after login.
We have a web-application developed using struts2, spring & hibernate.
The application needs a functionality that one user can login from only one browser.
Say if user x, is logged in on pc-1 browser ff, then he cannot be logged in from any other place.
I tried it by implemention session map and store the sessions in global map, but this fails when user logs off and tries to login again.
Even it fails critically if the user does not logs off and session time-outs, but the map is not cleared.
Any better idea to implement this functionality.
We do not want to obstruct the user to login but do not want users to exploit the application by allowing him to share the creditionals and allow multiple users with same login to happen.
Since you are already using Spring, I would recommend you to integrate your application with Spring Security.
Spring security lets you define maximum sessions allowed per user concurrently.
<session-management>
<concurrency-control max-sessions="1" />
</session-management>
If set when user having valid session tries to login again it will inform user that maximum concurrent access is set to 1.
Read more at the reference documentation of Spring Security: v3.2.x, v4.2.x or v5.1.x.
If spring security is not an option for you then:
Use a SessionInterceptor which will check for session validity, if session is valid it will check if user is already logged in to the application (for this you will have to maintain session somewhere for eg database for every successful login), if valid login is found, redirect user again to login page with custom message, or logout already valid session and then redirect him to login again. If you logout earlier session it would mean any successive action in that browser session will have to deal with invalid session.
If case you are also using Servlet in your application then Interceptor wont work for you, in this case you should use a Filter and follow the same steps as detailed above for Interceptor.
The best solution is to log-off user from other session when he logs in in new session. It is often that user would not logoff when closing browser and restricting him from logging in other window would be the pitfall.
Automaticly closing any previous user sessions is good, because in normal usage, it is no problem, but when sharing login and password, no two persons can work simultanously with your application.
At the login give the user a generated ID/cookie (sessionid suffices) stored with the user data. If a user does a request to the server with an old ID/cookie, say that he logged in elsewhere.
The other way round, forbidding the new login attempt, has its drawbacks - as you've experienced.
Create a map.
At the time of logging check that user id is present into that map or not.
If its not exist then put user id into map, at the time of logout remove that user id.
To be honest I would revisit the reasons why you have to restrict a user to a single login. Whilst preventing them from logging in from two different browsers is easy enough - any of the suggestions provided would work - with the Spring Security option being the easiest to implement if you can - they all break down when your user opens a second tab in the same browser. That is considered to be part of the same session.
Maintain user stack in servlet context,as it will be one for web container.perform a check before user getting logged in, if user name found in servlet context redirect him to login page.
All you should do is add a field in database userprofile table saying: alreadyLogin.
If user logins, make it Y. If user logs out, make it N. Now every time when user tries to login from new location, check this value and prevent login if Value is Y.
As many said, you can have a Map<String, User> (static Map or better an attribute in ServletContext) of (sessionId, user) of active users.
When a user tries to login, first check the existence in theMap.values(), and if it is okay add it to theMap.
Instead of removing from theMap on logout, implement a javax.servlet.http.HttpSessionListener, and on sessionDestroyed method, remove the item from it (the parameter of the method gives you the sessionId). This way if a user closes the browser, after session timeout period, it will be removed automatically.
On logout, invalidate the session, so it will be destroyed, and again this listener get executed.
Don't forget adding the listener to your web.xml.
In Spring security (3.0.6), if we try to access a page, and the session times out, we are taken to the login page, and upon successful authentication, we are redirected to the very page that we had tried to access before we were taken to the login page. Where, in the filter interceptor chain, is this 'last-accessed' url saved ?
I wish to modify this 'last accessed' url in the particular case when it redirects to '/exitUser'. How can I do that ?
A copy of the incoming request is cached (not just the URL), before redirecting to the login page. The ExceptionTranslationFilter realises that a login is required and passes the request to the configured instance of RequestCache. There is a basic description in the reference manual.
You can access the SavedRequest by requesting it from the RequestCache. By default it is stored in the session, so creating an HttpSessionRequestCache will give you the required functionality. You can also customize the RequestCache if you wish by using the namespace.
The actual redirect, which uses the saved request, is performed by the AuthenticationSuccessHandler instance. You can customize that if you want to change the redirect for a successful login. You'll find more on that in the manual and also in previous SO questions.
Im working in a Web App with Java and JSF. I have a simple login, if it finds the user in the database it creates a session and stores some information on it. That works great.
The thing is, I want to avoid two different people using the same user name and password at the same time. Something like account sharing. Only one user logged at one time.
I have been thinking this but I can't find the correct approach.
Thanks in advance for all your help.
One way I can think of is to put a boolean field logged_in to the database and set it to true whenever someone log in and set it to false whenever someone log out or session expired. Set it to false when someone log out is easy. For the session expired part, I believe using JSF, you have a SessionScope managed bean storing information about the user after he log in. You can implement a #PreDestroy method for that managed bean and ask it to set the field to false before it is deleted on session expired event.
When someone send "username" and "password" to the server through the login panel, you just need to check if the logged_in field is true or not.
You can create an application scoped bean for keep track which users are currently login to the web application. When a bean is in the application scoped ,all the request/response cycles for all clients will use the same bean instance .
You may declare a HashSet in this application scoped bean to store all the currently login userID . When a user login , checks whether his userID is inside the HashSet. If yes , it means he login already . Otherwise , it means he does not login yet .
Whenever a user successfully login , put his userID into the HashSet.Whenever a user logout , remove his userID from the HashSet.For the expired of a user session , use HttpSessionListener or #PreDestroy to capture this event and remove the corresponding userID from the HashSet.
For how to use capture the session expired event , you can refer to this.
For how to force an application-scoped bean to instantiate when the webapps starts , you can refer to this
I have a series signup pages that build on each other. When the users session expires I have a Listener that cleans everything up on the server and that works great. But, if the user attempts to do anything else I just want to redirect them back to the first page of the series. However, my filter doesn't seem to work correctly. I keep getting javax.faces.application.ViewExpiredException
What is the best practice for handling this expcetion? I can't really just handle in web.xml because that's too global. Plus the Error page is being rendered from some JSF code - it seems like I need to catch that this is happening using a PhaseListener so the exception doesn't happen in the first place, but I haven't been able to find a good model for how to do this. Any ideas?
Richfaces has their own mechanism for handling ViewExpiredException, look at Richfaces docs.
I think you are the correct track with a phase listener. Essentially set something up in session on the first page. Then in phase listener look for the value in session. If it doesn't exit then do a redirect. The trick is to do it early in the phase listener process.
Not sure exactly where in the process your phase listener is throwing the exception.
The way I handle this is to add a filter to the web.xml only mapped to the urls you want to track. That filter checks if the session is expired, and then forwards to a login page if it is. It should work if the filter is run before any JSF code is run.
The way I have handled this in the past is to use a listener which checks a field in a managed session bean. If the users session times out a listener cleans up the mbean and marks the user as not logged in. Every request is sent through the listener and if the requirements are not met then the user is forced out of the site. I never get ViewExpiredException in my log. The only time this exception has occurred is if the server has been restarted and the user requests a page when having a previous active session.
You can check whether you session is invalidate or not
boolean sessionInValid = httpServletRequest.getRequestedSessionId()
!= null &&
!httpServletRequest.isRequestedSessionIdValid();
Here the boolean variable sessionInValid will return true if the session is invalidate by any means.
You can add this in a filter or a listener then configure this in your web.xml file.