As some of you probably know, Facebook is using this kind of "system" where a popup is displayed when a user session is lost due to inactivity or distant session close. I already saw and read this Node.js question but didn't find anything.
I am working for a Canadian computer business our main product is a CRM and everything is coded using Classic ASP.
I know.
The whole web-based application is working great and since we host the site on our servers, it is possible if necessary to open ports and use sockets.
Here goes the main question: is there a way (using a javascript library or a jQuery plug-in maybe?) to trigger a client-side event when the session expires or is simply lost due to a server reset for example?
Of course, the best would be to use another solution than sending an AJAX request every second to validate if the user session still exists. If it can help, there is a maximum of about 3'500 users connected at the same time and our servers can easily handle more traffic. The servers are working on Windows Server 2008 along with IIS 7.
Unfortunately, I cannot provide any code blocks or screenshots for this question since there is nothing to debug.
One idea would be to use an AJAX request to a file that does not return anything and hangs there. If session is lost (inactivity or server reset), the AJAX request will trigger an error and the "error" function will be triggered. Would that be something to consider?
Or else, any other suggestions?
One way to do it is to set client-side timer set to the same time as session expiration time.
Let's say your session is set to expire after 20 minutes. When page loads - client-side timer set to 20 minutes kicks in. If user does any server interaction (submits form etc.) - timer is reset. But if nothing happens during this 20 minutes - timer counts down and you get your event.
You could do the following to achieve this, assuming you have a default session timeout of 20:00 minutes:
Ensure, that each user has a "session cookie" issued by you, NOT the default ASP Session Cookie.
dim live_session_id
live_session_id = Request.Cookies("livesession")
if live_session_id = "" then
live_session_id = create_unique_session_id()
Response.Cookies("livesession") = live_session_id
end if
Save this live_session_id in a database along with the expected session expire date
call updateSession(live_session_id, dateadd("n", 20, now())) ' = now()+20min
Output the live_session_id somewhere on your page, so you can access it via JS.
Implement a serverside ASP script that checks the current session state for a given live_session_id and make it accessible in IIS in a DIFFERENT subdomain, so calls to this check will NOT refresh the ASP session. The script could return the time difference between now and session end, so you could output the duration the session will remain valid.
Add some AJAX code to call the check script every other second, so you could issue a warning if the session time draws to an end.
To make it detect IIS reset, you could clear the saved sessions in the database by implementing Application_OnStart in global.asa. This way, your clients would detect a session loss by IIS reset.
another quick and dirty method
On every page load, you could let a javascript count down from 20:00 minutes and display a session lost warning after this time. This is what my online banking system uses... :)
as far as i understand you the main Problem is that the user has to fill out enormous forms. that could take some time and during that time the session could expire.
furthermore the session could be ended by anything else (iisreset or so) during the time the user fills out the form.
in my understanding you do not have to notify the Client that the session is lost/expired/ended/abandoned. it would be enough to just show a Login form (Ajax or something) when the user submits the form OR the next request (by Ajax as you mentioned) is made by the Client.
the called asp script checks if the session is valid and if not a popup or overlay is shown to Login the user by Ajax first and the form is submitted afterwards.
you could think of a http Status code 401 or something to send back to the Client and the Client then Shows the mentioned Ajax Login form...
What makes a session expire in your CRM? Expiring after X time passes since last [user] action is pretty conventional and will allow you to use ajax to keep the session alive. Let's say a session is good for 5 minutes as part of security requirements for super-secret NSA banking CRM with kittens and youtube videos. A good scenario of how a session can be extended would be this:
a page is opened, validating the session for another 5 minutes
a timeout is set with JS to make an ajax request every 4 minutes
[4 minutes later] the request is made, returning a very light-weight response.
if the response says everything is ok and the session is still valid, schedule another "ping" and carry on as usual. If the response comes back with an error (session invalidated on the server because of logging in from a different PC etc.), gracefully handle it. Allow the users to retain what they were working, don't just kick them out to a log in screen with an error
User navigates away from the page (clicks a link, submits a form), repeat from the beginning. If the user navigates to an external site or closes the browser, his session will self-destruct in no more than 5 minutes :)
Obviously you can piggy-back any additional information onto the ajax call in step 3 - e.g. notifying the user of new items assigned to them in CRM?
Google is your friend, one of the first results gives a not bad overview of the approach basics.
Related
I do not know how to detect it is the first time that user login the web.
I thought i should write a pop-up span on the jsp that user firstly saw when he login.but the issue is then he refresh the page,the notic will show again,that is ridiculous.
I need detect if it is first login means to detect if the user JUST LOGIN or NOT REFRESH the page
how and where shall I detect if it is the first time user login ? and then i can make mind if the notice span pop up.
and I think it should use cookies or session,but which one should i use?
Maintain a field in database table that check if it is first login than show a popup and after that change the value of that field so that Popup do not appear next time.
Ex:
if($data['first_login'] == 1)
{
// show popup
}
If you want to show it only to the new user (the time user registers) you can use a table column in database where you can use it to check if the user if logging in for the first time (e.g firtsLogin the column name = 1 ). If he is logging in for the first time you show the pop-up and change the value of the field to 0.
Otherwise if you want to show to users that are logged in to a specific device for the first time you should use cookies.
I suppose that you want to detect the user logging in to your web-site the first time. There are multiple ways that you can do it depending on your desire to spend additional time writing the code, the location of your logging-in logic (client or server side), security that you want to have while proving your users with login functionality. In all cases - you would have to store the data whether the user has logged in for the first time. I think you are seeking a fast solution that will work without a big care for privacy or security as working with client-side cookies isn't the safest way to store data. The alternatives to cookies are web tokens, url query string, server-side sessions and data-base (RDBMS) storage.
Storing and retrieving the data on the client-side using COOKIES. They are the pieces stored in the user's web browser. Cookies were created to help servers remember the data about the user next time he enters the web-site. The most common usages are: to store location (if accepted by user), web-site locale (language in which the user was browsing the site), products added to cart, etc. Following that approach you can create cookie after the user has logged in to your web-site as follows:
This should be run by your JavaScript.
document.cookie = "firstLogin=true";
After having done that, you would have to add JavaScript logic that will hook-up to user's/client's COOKIE data and read up whether he has logged in the first time before.
This would probably look like a simple JavaScript cookie look-up.
var cookieData = document.cookie;
This will return all of your user's cookies that has been previously stored when he visited your web-site. It will return it as a string concatenated with "; ". If we had previously stored only one cookie, we would get firstLogin=true;
In case if you have multiple cookies set before, you would have to parse the cookie string and extract the data either imperatively by plain procedural JavaScript code or by writing the function which will be able to do that repeatedly. Detailed examples of writing such functions could be found here.
1) I need the following requirement to be satisfied:
Client's request(Long running process) should wait till the server is serving the request.
Current solution:
Client initiates the request followed by ping request every 5 sec to check the request status and
with that also maintains the session.
2) If the client moves to other tab in the application and comes back, The client should still show the process status and server should continue working on the request.
3) If the client closes the browser or logs out, the server should stop the process.
PS : Need the functionality for all the browsers after IE-9,Chrome and Firefox.
There are many ways to skin a cat, but this is how I would accomplish it.
1, assign unique identifier to the request (You most likely have done this as you're requesting the ready state every few seconds).
Set a member of their session data to the unique ID.
Set all your pages to load the JS needed to continually check the process, but the JS should NOT use any identifier.
In the script that parses the ajax request, have it check the session for the unique identifier, and update an internal system (file or database) with the time of the last request and the unique identifier.
and push back details if there are details to be pushed.
In another system(like a cron system) or within the process itself(if in a loop for example) have it check the same database or file system that gets updated with the timestamp for the unique identifier and the last timestamp. If the timestamp is too old, lets say 15 seconds (remember page load times may delay the 5 second interval), then kill the process if cron'd, or suicide the process if within the process script itself.
Logout will kill the session data, thus making the updating of the table/file impossible(and a check should be there for this) and that will make it so that in the next few seconds from logout, the process stops.
You will not be able to find a reliable solution for logout. window.onbeforeunload will not allow you to communicate with the server (you can only prompt the user using only the built-in dialog, and that's pretty much it). Perhaps, instead of finding a solution on capturing logout/abandon, add some logic to the server's process to wait for those pings (maybe allow 30 seconds of no-comm before abandoning); that way you're not wasting server's cycles that much and you still have the monitoring working as before.
I'm working on an ASP classic application running on IIS 7.5. I am attempting to throw a popup overlay over the user's window if their session has timed out without them ever having to interact with the machine (for instance if they walk away from the machine and forget about it, I want this popup to be waiting for them when they get back).
I have implemented a background setInverval function that uses jQuery to send an ajax request to a page on my server named ajax-check-session.asp.
ajax-check-session.asp does nothing but check if the session still exists or not, and Response.Write a 1 or 0 respectively.
The session checking works, I can log out from a different tab and the pop-up will show up in any other tabs that were using that session. However, if I just leave the tab alone for 20 minutes (the Session.Timeout value), the pop-up never shows up. I'm assuming this is because the ajax request to ajax-check-session.asp is refreshing the session every 3 seconds so that it will never time out.
Here's the code for ajax-check-session.asp:
<%Option Explicit
Response.Write LoggedIn()
Function LoggedIn
Dim strUsername
strUsername = Session("username")
If strUsername = "" Or isNull(strUsername) Then
LoggedIn = 0
Else
LoggedIn = 1
End If
End Function
%>
Does anyone know if accessing this page every 3 seconds is, in fact, the reason my session won't time out? If so, do you have any suggestions for alternative techniques to accomplish my goal, or a fix to my code/server that will allow this page to not refresh session?
I have attempted using <%#EnableSessionState=False%> on this page, but I can't think of a way to still check if the session has expired with this set to false, as this seems to revoke access to Session entirely.
it's correct when you calling Session("username") in fact you are refreshing the Session Object itself, because that you will never see the popup.
an alternative is to use the Global.ASA file to implement a the functions Session_OnStart and Session_OnEnd to store the SessionID and the date/time when it was created in a database, and your script can check the records.
you can use both function to insert and delete the session info from the table.
Global.Asa Sintax (MSDN)
I have an ajax heavy website that breaks (or shows incorrect data) when users have it open in multiple browser windows at the same time. So I would like to enforce only allowing the user to be logged in to the website in one tab at a time, whether it is on the same computer or even multiple computers.
I am looking for ideas on how to do this.
Is there any JavaScript method to tell if a certain page is already open in another tab?
Perhaps there is another solution that could involve the server side..
For instance, the client could message the server every say, 1 minute. If the server gets messages from a certain users at a frequency higher than one message per minute, it knows that it is open in more than one window or tab. It can then let one of the clients know that it needs to shout an error to the user.
The idea of messaging the server every one minute does not sit that well with me though.
Any other ideas out there?
EDIT: some people are wondering why I have this problem in the first place. Here it goes:
This is a time tracking application that is fully ajax. You can browse/create/delete/modify timers, projects and clients with ajax, without ever leaving the page. If the website is open in multiple tabs, things will get inconsistent very quickly. Errors usually even occur. For instance, user creates a project and then starts a timer in tab1, tab2 will not show these changes. And since it is all ajax, it will not simply sync when the user clicks some button in the second tab.
Having read the update in your question, what I would really suggest is using WebSocket where available, falling back to Flash socket, long polling and forever iframe for older browsers (actually I'd use Socket.IO to make it all easy - you can use a similar abstraction for whatever environment you are using). That way you can make all of your windows and tabs consistent in real time - problem solved.
That having been said if you don't want to do it for some reason (though what you are trying to do would be a perfect application for WebSockets so think about it) you might use sessionStorage and localStorage to distinguish sessions between tabs or windows for the same logged in user, but it is not widely available yet - see the compatibility table so it would be probably easier to go real-time with a socket.io-like solution where there are a lot of fallbacks available than to restrict visitors to one tab - not to mention the user experience.
There's no way to get information about other tabs/windows in javascript (and for good reason).
The best way I can think to do it would be to print a unique identifier (a timestamp should work reasonably well) in the javascript code for each page, and then it periodically ping the server with that unique ID, and associate it on the server with the user. This way if you have more than one ID belonging to a single user being pinged within a given interval, you can send back a response to the page to warn the user that having multiple tabs open will result in unexpected behavior.
(Like Caspar said above though, you should really figure out why the unexpected behavior is happening and fix that rather than force the user to act a certain way)
This is pretty lo-fi, but I think the simplicity may make it work: you could try having the login open the session in a named window (or change the name of the current window). Then, on load inside the application, check to see if the browser window name is the one you've allowed them to use; if not, pop up an alert, close the window, focus on the named window, if still there. (If not there--i.e., they've already closed the other window--you could let this one stay open, and change the name to the correct name.)
So you're essentially using window.name and window.opener. Rough idea, but an idea.
I have a similar situation and the solution I use is:
on server: at every login you create an unique ID, save it (ex. database) and return it to client.
on client: on every transaction you send this ID to server as a parameter.
on server: if saved and received ID match then allow the request to execute if not refuse it with an error code.
on client: if transaction failed with specific code then you know that "ID" verification failed and you logout user.
So in this way if the same credentials will be used again in any other tab, browser, PC, country,... the old tab will logout user on next transaction request. Or in other words limiting only one opened page per user on the whole world.
Edit:
As I have stopped using html requests for any data communication and use websockets, I register user on server and if same user wants to login from some other location I close the previously used socket (the page automatically logs out).
In this way I also have a way to trigger full page reloads from server in case admin does something that influences users.
Simply use cookies.
$(window).on('beforeunload onbeforeunload', function(){
document.cookie = 'ic_window_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
});
function validateCallCenterTab() {
var win_id_cookie_duration = 10; // in seconds
if (!window.name) {
window.name = Math.random().toString();
}
if (!getCookie('ic_window_id') || window.name === getCookie('ic_window_id')) {
// This means they are using just one tab. Set/clobber the cookie to prolong the tab's validity.
setCookie('ic_window_id', window.name, win_id_cookie_duration);
} else if (getCookie('ic_window_id') !== window.name) {
// this means another browser tab is open, alert them to close the tabs until there is only one remaining
var message = 'You cannot have this website open in multiple tabs. ' +
'Please close them until there is only one remaining. Thanks!';
$('html').html(message);
clearInterval(callCenterInterval);
throw 'Multiple call center tabs error. Program terminating.';
}
}
callCenterInterval = setInterval(validateCallCenterTab, 3000);
}
I made a chat using PHP and JavaScript chat and there is a disconnect button which removes user from the chat removing him from user list first. But if the user closes browser then he will remain in the user list. How do I check if he left?
This must be done without putting any handles on page closing in JS because if user kills the browser then he will remain in chat.
By the way , JS script always sends a request to the PHP page which constantly checks for new messages in a loop and when there are some, the script prints them out and exits. Then it repeats all over again.
EDIT : How do I make a heartbeat thing in PHP? If a user closes the page the script execution will be terminated therefore we won't be able to check if the user is still connected in the same script.
Sorry, there is no reliable way of doing this, that's the way HTTP was built - it's a "pull" protocol.
The only solution I can think of is that "valid" and logged in clients must query the server in a very small interval. If they don't, they're logged out.
you could send a tiny ajax call to your server every 5 seconds. and users that doesn't do this aren't in the room any more
You answered your own question: if you don't detect a request for new messages from a user over a given length of time (more than a few seconds), then they left the room.
The nature of HTTP dictates that you need to do some AJAX type of communication. If you don't want to listen for the "give me more messages" request (not sure why you wouldn't want to), then build in a heartbeat type communication.
If you can't modify the JS code for some reason, there really is little you can do. Only thing you can do with PHP is to check if there's been for example over 15 minutes from the last activity, the user has left. But this is in no way a smart thing to do – a user might just sit and watch the conversation for 15 minutes.
Only proper way to do is using AJAX polling in set intervals if you want to do it reliably.
You noted that a user polls the server for new messages constantly, can't you use that to detect if user has left?
Maintain a list of active users on the server, as well as the last time they connected to the chat to request new messages.
When a user connects to check for messages update their time.
Whenever your code runs iterate through this list and remove users who haven't connected in too long.
The only failure is that if the number of users in the channel drops to zero, the server wont notice until someone comes back.
To address your edit, you can ignore client termination by using ignore_user_abort.
Using javascript u can do the following :
<script type="text/javascript">
window.onunload = unloadPage;
function unloadPage()
{
alert("unload event detected!");
}
</script>
Make the necessary ajax call on the unloadPage() function to ur PHP Script
Request a PHP script that goes a little something like this, with AJAX:
register_shutdown_function("disconnect_current_user");
header('Content-type: multipart/x-mixed-replace; boundary="pulse"');
while(true) {
echo "--pulse\r\n.\r\n";
sleep(2);
}
This way, you won't constantly be opening/closing connections.
The answers to all the questions asked by the OP are covered in the section in the manual about connection handling:
http://uk3.php.net/manual/en/features.connection-handling.php
No Ajax.
No Javascript.
No keep alives.
C.