i wanted to throw an alert when session expires and when you press ok button in the alert box then it will take you to login page. For this i thought to create a timer and timertask and in the run method of the later class i will check if the session exists or not. So for this i tried to create a class in jsp page but it is showing error. i can create in servlet but all my pages are in jsp and so this idea is not useful.Now i created a sessionlistner and in the session destroyed method i want to link to login page but i have a problem here too.I can not use response method in the sessiondestroyed method.Please tell me are there any other ways
You can use JavaScript like:
var sessionTimeout = "<%= Session.Timeout %>";
function DisplaySessionTimeout()
{
//assigning minutes left to session timeout to Label
document.getElementById("<%= lblSessionTime.ClientID %>").innerText =
sessionTimeout;
sessionTimeout = sessionTimeout - 1;
//if session is not less than 0
if (sessionTimeout >= 0)
//call the function again after 1 minute delay
window.setTimeout("DisplaySessionTimeout()", 60000);
else
{
//show message box
alert("Your current Session is over.");
}
}
For more details visit here
First, you can creates totally client side solution: use setTimout() when page is loaded first time. Use either hard-coded or arrived from server value of timeout. When timer is triggered use document.location = login.html (or something like this) to arrive to login page.
This solution is "fast and dirty."
Better solution should be based on real session expiration. You can create AJAX call that tries from time to time special URL. This URL should return true/false that means that session is expired or not. When session is expired you should redirect the page to login screen. The problem with this solution is that the fact that you request the session state refreshes it. To solve this problem you can either perform the request to different server or (probably) remove session cookie from the polling request, so it will be performed in session different from the main session.
With Tomcat you can create a JS timer that make a simple AJAX call.
If the call return without errors the session is valid, if the call fails you can consider the session expired. On default behavior Tomcat deosn't renew sessions if you don't explicitly call it.
I had the opposit case: link
This problem is already solved by the Java EE Spec. You should consider using web.xml configurations to handle session timeout issues. It has specific tags for handling all of this. Some of the tags are:
<login-config> ... </login-config>
The above tag lets you used FORM based authentication where you can specify your login HTML resource.
<security-constraint> ... </security-constraint>
The above tag lets you specify the URLs you would like to secure. And finally the session timeout tag itself, which allows you to specify the session timeout in millis.
Once you do the above, the container would automatically take the user to the login page when he requests a secure URL.
Here is the web.xml reference.
From a messaging standpoint, there are multiple ways of seeing the problem:
The fact that system is taking the user back to the login page and forcing him to login, is indicator enough for him/her.
You could provide a generic message on the login page itself.
Device some tricky flag based or querystring logic to show the message on the login page.
Came across this link in StackOverflow itself which provides a strategy you can implement in the login page itself. Have not tried this though.
This in my mind is a trivial problem compared to the whole session timeout strategy itself.
Related
I have set max concurrent sessions to one.
Now there are 2 situations I want to handle if there is an active session (Someone is already logged in for that User Id):
If the user accesses login page again on the same browser:
In this case, he will be directly logged in.
If the user logs in from different browser/client machine: In this case, need to show the error "A session is already active for this user. Are you sure you want to overwrite the session?". If the user selects 'yes', the error will be shown at the previous session (this I know error page can be configured), and if he selects no, it will not login, the previous session will persist.
How can these usecases be achieved using spring security? So far, I have been able to found the basic management of concurrent sessions, by setting max session count and error page.
Please help.
Thanks.
I think you have almost done it. To ask user before overwriting a session follow the below steps.
The expiredUrl property of ConcurrentSessionFilter should got to a page where the UI is provided to ask user (e.g. askUser.html).
The askUser.html form submits to another url (e.g. /api/confirmSessionRewrite) with POST parameter yes or no.
In controller ConfirmSessionRewrite either remove the user from session registry or forward it to login page.
sessionRegistry.removeSessionInformation(info.getSessionId());
You have to modify your config so that the ConcurrentSessionFilter would not run on /api/confirmSessionRewrite request. Otherwise it will be a loop.
In our JAVA web application we maintain users' session in a database table active_sessions. And we do not allow multiple sessions per user. what it means is, if you are already logged in with a particular user account, you cannot open a new session with the same account. In case somebody does, we display error 'User already has an active session'. When user clicks on Logout his entry from table active_sessions is removed. But in case where user closes the window without logging out his entry remains in the table active_sessions. So any attempt to login in future results in an error 'User already has an active session'. Any tips on how to destroy user session in database in case he closes the browser window without logging out.
Edit: After reading all the posts it seems there is no clean way to restrict single session per user.
Use the 'onbeforeonload' JavaScript event which can perform an AJAX call to your server to delete the entry. This event will however be executed each time the page is unloaded so if you don't have a SPA then you'll need to ignore the event for href and such.
Agree with Almas however that your approach is dangerous in the sense that it is not possible to enforce this 100%. E.g. if the user kills the browser process then even this JS event would not be published.
Furthermore, a user can simply use another browser to bypass your 'protection'.
In the server side users HTTP session is normally invalided after a certain period of idle time. You can implement http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpSessionListener.html and register it in web.xml to receive notifications about session create/destroy etc. In your listener implementation you could delete the table entry on session destroy event.
The basic thing about HTTP is that it is request/response protocol.
i.e. Things are changed/accessed only by making a request to the server. This 'limitation' makes your requirement interesting. There can be two workarounds for this:-
Poll the server at a repeated interval through an AJAX call. As long as you application keeps getting the polling AJAX request you can assume that the window is open.
Use javascript (window.onunload ) to fire an event to destroy user session when the browser is closed.
Using onuload
how can i see logout time when user closes the browser without logout?
So i implemented HttpSessionBindingListener taken from here and added Listener in web.xml but logout time is not being inserted into database after closing browser. Any suggestion please where i am wrong?
logout.jsp
<%
ObjectWillBeInSession owi = new ObjectWillBeInSession();
owi.setProperty1("I am a value for Property1");
owi.setProperty2("I am a value for Property2");
//this will call HttpSessionBindingListener's
//valueBound method for the object
session.setAttribute("owi", owi);
//this will call HttpSessionBindingListener's
//valueUnbound method for the object
session.removeAttribute("owi");
//INSERT INTO DB.......BUT IT IS NOT WORKING
%>
Closing the browser does not trigger any request to the server, so there is no way you can know that the user closed his browser.
You can use a listener to way for the session to time out and then store the current time when that happens. Session typically expire hours after the last request from the client, though.
You can use JavaScript's window.onbeforeunload to send an AJAX request to a servlet to record the time the user closed the browser and do what you need in the session object.
Sorry for the broad topic. Basically, WSC is supposed to have out-of-the-box session timeout handling by forwarding the user to the ReLogonFormView, which the user can presumably configure (through Struts) to any jsp that they choose. We use a custom logoff command, and it seems to be affecting that view showing up.
I'm not looking for a specific solution to this problem, I'm just looking for general knowledge about how WSC (v6) handles session timeouts (how it determines that the session has timed out) and what command(s) it runs by default when / if / to determine the session has expired.
This is my current knowledge on this subject...
The session timeout is a global value for all web modules and can be found in the wc-server.xml and is set to 30 minutes OOTB.
When a timout occurs, the OOTB LogoffCmd would normally be called, which will set up the necessary URLs to navigate to the ReLogonFormView URL while keeping hold of the URL where the session timeout occurred.
If the ReLogonFormView contains userid/password fields to allow the user to logon again, the user will then be redirected back to the page they were originally on.
More info can be found in IBM InfoCenter under "LoginTimeout".
If you extend the OOTB LogonCmdImpl, you should not try and set the forwarding URL, or that will interfere with the OOTB navigation.
I think you should perform your custom logoff functionality and then call super.performExecute() to allow the OOTB navigation logic to take over.
Note: You can retrieve the URL you were originally on via a call to getReferrerURL() and the ReLogonFormView should be returned from getURL().
We have a spring security application with a pretty standard setup. Currently we only allow 1 session per principal, rejecting additional logins by the same principal until the first session is logged out or expired (maximumSessions=1, excpeptionIfMaximumExceeded=true).
I'd like to change this so that when a principal logs in a second time with a currently active login on another session the first session is invalidated/replaced. This is easily accomplished using the provided spring security concurrent session control strategy but I am having trouble figuring out how to alert the user. When a user's session is replaced the session is invalidated by the logout handler. The next request will get a redirect to the login page with a error code on the query string. However, if the request which gets this redirect is an image or other non-programatic call I'm unable to handle this.
It seems like I need to put the user into an inbetween state, where they have a session but it is expired and they need to log back in if they didn't mean to replace their original session. However I don't see a good way to do this.
Is there an example of a setup like this somewhere?
Have you thought of working out a polling mechanism in javascript to alert the user when their session is about to be invalidated? This way they will know that their session isnt valid and possibly have a chance to refresh it in case they have partially filled out forms or text areas.
This can also work from the login side. You can add a step after login if they have another session active and have them verify they want to invalidate it.
It seems that an in between step isnt necessary because, generally,authentication should be boolean. Either they are authenticated or they arent. The inbetween zone might be tougher to handle all cases for.