I am using timestamp till nano second as a user session, say tab A has session1 and user opens tab B say this session is session2 and now session1 gets only inactivated after some file upload activity is done at this point of time I want the session2 be still active.
How do I do this without using cookies?
have you looked into html5 sessionStorage/localStorage ?
these apis sport a client-side storage facility pretty similar to cookies which you can employ to manage sessions. the lifetime of the database is either the lifetime of the respective tab/window (ssessionStorage) or the interval between two consecutive deletions the pertaining browser data; the latter may depend on the browser preferences (eg. automatically after closing the tab/window in privacy mode or upon express user request).
for a start, mdn has something to say about it. there also is a full-fledged tutorial on html5rocks.
the gritty in-depth w3c standard details all about the programmatic (javascript) interface.
the api do not provide facilities to exchange information between client and server. one option to handle this part would be encoding the information into urls (client -> server) or http headers (server -> client) being called/received through ajax.
a final word of warning: for security reasons, do not store authenticating data this way.
say tab A has session1 and user opens tab B say this session is session2
This is already impossible. Both tabs will be in the same session. If tab B created a new session due to a login for example, tab A will now be in the new session.
and now session1 gets only inactivated after some file upload activity
It won't happen.
is done at this point of time I want the session2 be still active.
It still is. Session 1 will have been destroyed if it's different from session 2.
Related
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
Scenario:
User logs into website.com using firefox. Login credentials are valid, user is directed to member's page.
User tries to log in to website.com using chrome. Login credentials are valid, because use is already logged in using firefox, system will throw error, asks user to close other session to login through chrome.
How can I detect that? Right now I am able to detect it if user only use one browser, but seems to break when user uses two different browsers to log in at different times.
EDIT* I want to say it's more than just using different browsers, the website should not allow multiple people to log in with the same login credentials.
I am assuming your application is j2EE/servlet based. If it is the case, two browsers are independent of each other, hence they have their own sessionId and can function independently, as long as your application does not interfere.
To prevent this scenario, one way to implement is, keep a hashmap of SessionID and UserID in your servlet. You populate this on every successful login, for example via a filter or a valve. When you are populating the hashmap, make a check, to see if any other sessionID is already using this userID. If it is used, check if the corresponding sessionID is still active. If it is not active, allow the login, and delete the stale sessionID. If it is active, terminate the other session and allow the login.
If you're using Spring Security - it may be specified by parameter in the configuration file.
If just plain java - during log-in put user's session id to some storage; when he tries to log-in again you should prohibit it.
But you need to avoid situation when the user will be in storage very long time after closing the browser (one possible solution is short session timeout + keep-alive requests)
In your application, keep a timeout of the user that's updated after each call to the app. You can define the user as 'locked' into a session (for example your firefox session) until either the timeout expires, or the user requests a logout. When you log in on another browse (for example, chrome) it checks to see if there's an active session and, if there is, denies the login attempt.
I'm going to make up a quick example. This isn't even close to production ready and is for illustrative purposes only.
class User {
long lastCheckin;
int userId;
String username;
}
Now, when someone does anything in the app, like viewing a page, you do this
user.lastCheckin = System.currentTimeMillis();
Now, when someone specifically requests a logout, you do this
user.lastCheckin = 0L;
Now, when someone tries to log in, you do this
if(user.lastCheckin + PREDEFINED_TIMEOUT > System.currentTimeMillis()) {
return new LoginResponse(false,"User is active in another session.");
}
You can store a map of logged-in users on an application scope variable like a ServletContext. For example, on your auth servlet, you can probably do something like:
Map<String,String> activeUsers = request.getSession().getServletContext().getAttribute("__ONLINE_AUTHENTICATED_USERS");
//if null, context hasn't been prepared yet, create and attach a new one?2
You have to be careful though. Being an application scope variable, you need to ensure some thread safety and this is something which the servletContext.setAttribute/getAttribute is providing(e.g. those operations are not thread safe). You may be able to handle this by using some sort of application lifecycle listener to 'initialize' the servletContext to have the user map. This way you won't need to worry about the set/getAttribute. You still need to think about the map operations themselves(e.g. use j.u.c.ConcurrentHashMap maybe?).
You also have to take care of cleaning up(e.g. removing from the map) when a user logs out or session times out.
You also have to consider that a user might lock himself out for a long time by this approach(e.g. close browser but do not logout properly, session needs to timeout before the mapping is cleared).
Edit:
You also need to think about scalability and this depends on your application. Are you expecting a million online users? Or only a couple of thousands?
How to invalidate a session when I click new tab window for same application(for same url)? Once I access the same url the existing session has opened. I want start different session for
When it comes to the session/cookie, browsers currently don't support separate cookies for each different tab/window.
But, some frameworks have this concept of Window so that using it you can be notified when a new window/tab is opened. Once you can detect it you can destroy the old windows. Updating the session (or invalidating and creating a new one) won't have the desired effect (even if you can do this) on the other tab as this whole thing might repeat when the user goes to the other old tab.
Your best bet is to keep multiple windows for the user in a single session.
If you are using simple servlet you can use following code,
// Get the existing session.
HttpSession session = request.getSession(false);
// Invalidate the existing session.
if(session!=null) {
session.invalidate();
}
You can call this servlet by doing mapping for your new tab url in web.xml.
Use Url rewriting for different sessions in different tabs/windows. If you want to invalidate the session, then just remove all previous sessions for that user. The only problem would be if someone copied and pasted the url. If this could be a problem, then look into somehow storing the session key in HTML5 storage.
Session ID is kept in a cookie, so you cannot have two different sessions for the same application in one browser (a new tab or a new window - doesn't matter) at the same time.
Your server session is mapped with the HTTP Session. You can not have two HTTP sessions at the same time in the same browser... And how would you identify that the has pressed Open in New Tab and he didn't open the link in the same tab? You should have an AJAX ping for that (pretty tricky...)
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().
I have a web app in which I have set the maximum inactivity time to 10 min. This is just for testing purposes. Basically, if the session has timeout and I click on a link, the following window browser checks if the session is valid. This is also working fine. If this happens, I get a message saying "session has expired, please login again". But the orginal window stays open and if I click on the same link, then this time is letting me see the page, even though I have not logged in again. Why is this?
I am using the session.invalidate() if the session is expired, to make sure all attributes are removed, but this is not working somehow.
I using the following part of the code at the beginning of the page:
if(request.isRequestedSessionIdValid() == false)
{
response.sendRedirect("expired.jsp");
session.invalidate();
return;
}
This is working the first time this page is loaded, but if I click on the link again to load it once more, this condition is not met, despite the session being timeout.
Could you please give any advice?
Update: My webapp works the following way:
User gets to the index.jsp page and uses an ID and password to access the system, then there is a BRMspace.jsp page where there is a folder structure for the user to access depending on the documents they are after. By clicking on each folder, a table with a database populated is displayed for the user to download the documents they want.
The issue I am having is that after 10 min of inactivity, if the user clicks on one folder on the initial screen, the database is not displayed, instead I get a message saying that session has expired and I am redirected to the login page, which is ideal. However, if I click on the same folder again, this time I get the usual table with the data and all documents. It seems that after one click, the inactivity time is not longer valid.... so I am not sure how to do... I am using session.invalidate() to delete all data about the session, but obvioulsy is not working.
I need the user to be redirected to login page again after the inactivity time no matter where the user clicks on.
This is an update:
Hi there, I have to re-take this question, which has been very helpful to resolve 90% of my original issue, but I still have one left.... on my web application, when user logins, they have a list of options to click on, each click takes them to a new tab which are different .jsp files... if session has expired, these tabs show the expired.jsp file, which is perfect... however, the original tab, the one that is shown after the user logins, stays live, I mean, it does not show that the session has expired... what can I do in this case?...
A web session doesn't have anything to do with any login or access credentials. It simply means that the container has data saved for you that can be retrieved if you pass in the correct session token (either by cookie or request parameter). If you have been inactive on the site for a period of time (in your case 10 minutes), that data is discarded and if you check for a sessions validity, you will discover whether the data is still around or has been discarded. If the session has expired, the container will automatically create a new session for you to handle future requests. And if another request is sent to the server before the timeout expires, that requested session will not be invalid.
If you are trying to prevent people from access a page when they have not logged in, you actually need to put some value into the session that says they have authenticated, and check that value. Just checking whether their requested session is valid is not sufficient.