I am working on PHP and MySql. I need a feature, when user close browser tab, a user should log out automatically.
I have used javascript onbeforeunload event. But it is not working, this event executes for page refresh also.
Here is my sample code,
window.onbeforeunload = function(){
$.ajax({url: "logout.php", success: true});
return 'Are you sure ?';
};
Idea would to poke the backend every 2 seconds and expire the session when you stop for let's say 5 seconds? This way 3 to 5 seconds after closing the tab session would automatically expire.
setInterval( function() {
$.get('/poke.php');
}, 2000);
While php side:
// poke.php
$_SESSION['poke'] = time();
// Probably your index.php
if (isset($_SESSION['poke'] && time() - $_SESSION['poke'] > 5) {
// Do the logout
} else {
$_SESSION['poke'] = time();
}
Related
Recently came across this problem. The scenario is, let's say I have two tabs open (A and B), I login with Tab A authenticates redirects to the home page. Then selected a link instead of just entering, I right click and pick "Open link in a new tab" thus having Tab B. At this point I start navigating for 30 mins a alert pop up saying my "Session has been finish. Please login again.". Instead of being redirected to the Login page I was redirected to the home page. (The alert must be coming for Tab A)
If I was dealing with only one Tab this isn't an Issue after the alert I would go directly to the Login Page.
I have two set of codes one handles the actual session expiration and the other gives out the alert.
This code is for the alert:
function idleLogout() {
var t;
window.onload = resetTimer;
window.onmousemove = resetTimer;
window.onmousedown = resetTimer;
window.onclick = resetTimer;
window.onscroll = resetTimer;
window.onkeypress = resetTimer;
function logout() {
alert("Session has been finish. Please login again.");
window.location.href = '{{url("")}}';
}
function resetTimer() {
clearTimeout(t);
t = setTimeout(logout, {{ env('SESSION_LIFETIME')*60*1000 }} );
}
}
idleLogout();
Code is working as intended but it can be implemented better.
Btw, if it matters using PHP Laravel 5
The problem is that you're using JavaScript to handle your timeouts. JavaScript (by default) is only confined to a single tab. While you could make use of COOKIES in JavaScript to communicate between tabs, it would make far more sense to handle session timeouts through server-side SESSION variables, which persist across tabs.
A thirty minute forced timeout can be achieved in PHP, courtesy of this answer:
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
// last request was more than 30 minutes ago
session_unset(); // unset $_SESSION variable for the run-time
session_destroy(); // destroy session data in storage
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
Hope this helps.
I am very beginner in web development. I spent some time realizing the way to limit session time in PHP. I have read Stackoverflow suggestions but none of them seems to work for me (cookies-might be edited by user, AJAX communication-extra load on server and static PHP - what about passive tabs in browser? Validation using session vars).
I have in mind this:
<script type="text/javascript">
$(document).ready(function() {
setTimeout(function() {
window.location.href = 'logout.php';
}, 10000);
});
</script>
...to limit session time for users. This system will be used in a management web app. Could anyone point out potential drawbacks of my approach, because it seems to be too simple to be good?
<?php
function check_user_is_valid () {
//Start our session.
session_start();
//Expire the session if user is inactive for 30
//minutes or more.
$expireAfter = 30;
//Check to see if our "last action" session
//variable has been set.
if(isset($_SESSION['last_action'])){
//Figure out how many seconds have passed
//since the user was last active.
$secondsInactive = time()-$_SESSION['last_action'];
//Convert our minutes into seconds.
$expireAfterSeconds = $expireAfter * 60;
//Check to see if they have been inactive for too long.
if($secondsInactive >= $expireAfterSeconds){
//User has been inactive for too long.
//Kill their session.
session_unset();
session_destroy();
}
}
}
//Assign the current timestamp as the user's
//latest activity
$_SESSION['last_action'] = time();
Call check_user_is_valid () function on every php page to check if the user have valid session.It will automatically destroy session if page is still for 30 minutes.
Update the value of $_SESSION['last_login'] variable with new time on every page, so that the user get 30 minutes session for each and every page.
How can I redirect to the login page when the session has completed? The code should check that the user sits idle for some time and then does any other client side event. If it finds this condition, it should check the session time out, and if session completes, redirect to login page.
Checking for inactivity on a webpage will be like an attempt to listen multitude of event. This also means that if there is user interaction the a function (event handler) is going to be called quite a lot of times. If this handler/function is going to some ajax send/receive stuffs then it could ultimately make your user interface perform poorly.
Why not make the session expiration period short and auto log out the user after? That way if the user is truly active then most probably there will a request for a page within that time frame. You could also set up a timer based event which when fired will simply send dummy request to server to refresh the session as a way of letting the server know that the user is still active but just not ready to request another page yet. This would be the case where a user is editing a long text or something like that.
I hope it helps.
Session Logout after 5 minutes
<sctipt>
var interval;
$(document).on('mousemove', function () {
clearInterval(interval);
var coutdown = 5 * 60, $timer = $('.timer'); // After 6 minutes session expired (mouse button click code)
$timer.text(coutdown);
interval = setInterval(function () {
$timer.text(--coutdown);
if (coutdown === 0) {
alert("Session expired User successfully logout.");
window.location = "UserLogin.aspx";
}
}, 1000);
}).mousemove();
var interval;
$(document).on('keydown', function () {
clearInterval(interval);
var coutdown = 7 * 60, $timer = $('.timer'); // After 6 minutes session expired (keyboard button press code)
$timer.text(coutdown);
interval = setInterval(function () {
$timer.text(--coutdown);
if (coutdown === 0) {
alert("Session expired User successfully logout.");
window.location = "UserLogin.aspx";
}
}, 1000);
}).mousemove();
<sctipt>
<div class="timer">
Time of session display on page
</div>
I really want to prompt my user to keep the session alive, shortly before it expires.
Yesterday, I asked the question "How can I check if the session is dead, then prompt an alert?" and somebody answered with an AJAX/JSON solution, that made calls every 30 seconds to an ASP page. This didn't work, as the calls to the server kept the session alive - so it would never log out.
I kept reading and came across a similar [SO] question, where somebody suggested using a JS countdown that prompted the user to renew the session, 5 minutes before the session is due to expire.
This is what I have done so far but:
The function startMainTimer does not seem to be keeping the time because I did not receive an alert when the timer was due to alert.
The $('body').mousedown() feature doesn't work as it should. It works but if a user clicks a link, the mousedown function works but doesn't follow the link after the function has run.
Here’s the code:
<script>
$(document).ready(function() {
$.ajax({ // get session expiration value e.g. 60
type : 'GET',
url : '../getSessionValue.asp',
dataType : 'text',
success : function(data) {
if (data != '') {
var newSessionValue = data - 5
startMainTimer(newSessionValue * 60000); // deduct 5 minutes, convert to mSeconds & call startNewTimer()
}
}
});
$('body').mousedown( function() { // if user clicks anywhere on page call ajaxRenewSession() function
ajaxRenewSession();
});
$('#userButtonRenewSession').click( function() { // if user clicks continue browsing button
ajaxRenewSession();
});
});
function startMainTimer(newSessionValue,restart) {
if (restart == 'yes') {
clearInterval(interval);
}
var counter = 0;
var interval = setInterval(function() {
counter++;
if (counter == newSessionValue) {
alert("Your session is about to expire!");
clearInterval(interval);
}
}, 1000);
}
function ajaxRenewSession() { // AJAX the server to renew session, get session timeout value and then reset JS timer
$.ajax({
type : 'GET',
url : '../renewSession.asp',
dataType : 'text',
success : function(data) {
if (data != '') {
var newSessionValue = data - 5
startMainTimer(newSessionValue * 60000, 'yes');
}
}
});
}
</script>
Can anybody help me rectify these problems?
The thing with mouseup seems to work, I tested it on stackoverflow.com. However, it may not work in some cases, e.g. if the user presses a link, drags it and then drops it. In this case, no event was raised for me.
Another thing: You will have to clear the main timer at the beginning of startMainTimer because otherwise, everytime the user clicks somewhere, an additional timer would be started.
And you know that the last call of startMainTimer misses a parameter?
i have a problem.
I am working on a chatting application. I want to kill the session if user closes the browser window without logging off. I used 'beforeunload' function but it also fires when a postback event is fired so it's not good for me.
Please help if anyone have any idea about it.
If you use polling to get the chat data, you should kill the session if you don't get a polling request from the client for a given time.
Client:
setInterval (pollData, 10000); /* poll for new data each 10 seconds */
Server:
if (clientX.LastPollTime is over 30 seconds ago) {
clientX.killSession();
}
I suggest you to use the Alexanders approach, but In most cases setting interval time wont alone solve this problem. Because the user may be idle for some time and it may exceed the timeout period.
In order to avoid this, yo need to add one more condition over this.
if the user is idle for the timeout period then Just make an AJAX request to server and update the client status as idle.
this will avoid logging off the session if the user is idel for certain time.
And you can terminate the session if the server didnt recieve any response from client in a specified time and the status is not updated to idle (during browser close or any application hangups).
yup dear, it is okey, but in second thing as you specified that that server didn't receive any response, in my code server only checks the application session and it will find it so it will work. what i want that if the user not log off then the page is killed and after that how can we call any ajax or xmlhttp request from client side to set the application session to offline.
so please guys tell me something this is the only thing is not going well. and thanx for your response.
As you said the event window.onbeforeunload fires when the users clicks on a link or refreshes the page, so it would not a good even to end a session.
However, you can place a JavaScript global variable on your pages to identify actions that should not trigger a logoff (by using an AJAX call from onbeforeonload, for example).
The script below relies on JQuery
/*
* autoLogoff.js
*
* Every valid navigation (form submit, click on links) should
* set this variable to true.
*
* If it is left to false the page will try to invalidate the
* session via an AJAX call
*/
var validNavigation = false;
/*
* Invokes the servlet /endSession to invalidate the session.
* No HTML output is returned
*/
function endSession() {
$.get("<whatever url will end your session>");
}
function wireUpEvents() {
/*
* For a list of events that triggers onbeforeunload on IE
* check http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
*/
window.onbeforeunload = function() {
if (!validNavigation) {
endSession();
}
}
// Attach the event click for all links in the page
$("a").bind("click", function() {
validNavigation = true;
});
// Attach the event submit for all forms in the page
$("form").bind("submit", function() {
validNavigation = true;
});
}
// Wire up the events as soon as the DOM tree is ready
$(document).ready(function() {
wireUpEvents();
});
This script may be included in all pages
<script type="text/javascript" src="js/autoLogoff.js"></script>
Let's go through this code:
var validNavigation = false;
window.onbeforeunload = function() {
if (!validNavigation) {
endSession();
}
}
// Attach the event click for all links in the page
$("a").bind("click", function() {
validNavigation = true;
});
// Attach the event submit for all forms in the page
$("form").bind("submit", function() {
validNavigation = true;
});
A global variable is defined at page level. If this variable is not set to true then the event windows.onbeforeonload will terminate the session.
An event handler is attached to every link and form in the page to set this variable to true, thus preventing the session from being terminated if the user is just submitting a form or clicking on a link.
function endSession() {
$.get("<whatever url will end your session>");
}
The session is terminated if the user closed the browser/tab or navigated away. In this case the global variable was not set to true and the script will do an AJAX call to whichever URL you want to end the session
This solution is server-side technology agnostic. It was not exaustively tested but it seems to work fine in my tests
PS: I already posted this answer in this question. I am not sure I should answer multiple questions that are similar or post a reference?
If you have control of sessionID cookie, just set its lifetime to 0, that makes the session die on browser close. The lifetime of the session on the open window can be controled from the server side storing the time last seen in the session and checking
if(isset($_COOKIE[session_name()])) {
setcookie(session_name(), $_COOKIE[session_name()], 0, "/"); // die # browser close
}
if(isset($_SESSION['last_time'])){
if( ( time() - $_SESSION['last_time'] ) > 300 ){ // 5 minutes timeout
// here kill session;
}
}
$_SESSION['last_time'] = time();
In the client side you can use the Daniel Melo's answer. I'm using it with one small change:
function endSession() {
// $.get("<whatever url will end your session>");
// kill the session id
document.cookie = 'MYOWNSESSID=; path=/';
}
The only pending matter is that i can't wireup events to input type[buttons] yet, i have made it with raw code, but the all thing works.