How to check if user has left certain page - php

Right now, when the user comes to a page a session is started; that's working fine. But how can I detect when a user leaves that page? I need it so that when the user leaves the page, the session is destroyed.

You wouldn't be able to use PHP to detect the user leaving the page, but you can send an ajax request via javascript on the unload event to destroy that users session.
Related post: Can you fire an event in JavaScript before the user closes the window?

If you're only worried about pages within your website:
if($_SERVER['REQUEST_URI'] !== 'page_with_session.php'){
session_destroy(); // Kill session for all pages but page_with_session.php
}

HTTP is an asynchronous protocol. Asynchronous connections with user sessions are valid in a certain period of time. This time is also refered as expiry time. Therefore sessions have an expiry time. And this time will be renewed while a user accesses your page and invalidated(destroyed) if he does no action in this timeframe.
There is no other way to determine if a user leaves your page.

It is impossible in general case

That's not really how the internet works; you could try sending a signal with onbeforeunload() but it's not a guarantee. Since session garbage is just a probability, and I don't know what your viewership looks like, I'd suggest putting something like this in a common file:
if (isset($_SESSION['last_seen']) && $_SESSION['last_seen'] < time() - 3600) {
session_unset();
session_destroy();
header('Location: logout_or_whatever.php');
exit;
}
$_SESSION['last_seen'] = time();

Related

Automatic refresh page and destroy session in php after 30 seconds of page inactivity, without any user interaction?

This code works perfectly when user press refresh after 30 sec of page inactivity, but i need some code to automatic destroy sassion and refresh page after 30 seconds of inactivity.
<?php
$inactive = 30;
ini_set('session.gc_maxlifetime', $inactive);
session_start();
if (isset($_SESSION['testing']) && time() - $_SESSION['testing'] > $inactive) {
session_unset(); // unset $_SESSION variable for this page
session_destroy(); // destroy session data
echo "<br><br>Sorry, you can't go any further!!!";
echo "<br>Please log in.";
echo "<br/><a href='index.php'>Go back to login page</a>";
}else{
//Here is some code to do when the session is still active
}
$_SESSION['testing'] = time();
?>
There are a few ways to approach this depending on how you want the user to be notified - if you simply want the page to be reloaded after the time has expired - this will work:
<meta http-equiv="refresh" content="30" >
if placed in the head tag of the page - basically this will cause the page to refresh after 30 seconds - which will cause your PHP code to execute again, which will produce the effect you want.
If you want a better user experience - i.e. not making the page just refresh but giving the user some kind of warning / prompt that something is about to expire - you need to use javascript - something like this would work (inside of a script tag on your page):
setTimeout(runAfterThirty, 30000);
function runAfterThirty() {
alert("Your session expired - I am going to refresh the page now");
location.reload();
}
inside of your function, you could put anything you want - you would most likely want something that changes the page rather than refreshes it.
Either way, the page is refreshed by the javascript, which means that your PHP code can execute. You should destroy the session with PHP.
You can achieve this slightly differently if you wish - by calling an AJAX request that will hit a page that is designed to destroy the session - however it looks like, based on your code - this is not needed - however an approach that used AJAX would mean the user's page did not need to refresh - the logic would be like this:
1) The page has some javascript code that calls a function after the time limit has expired (see above code) - that function then makes an AJAX request off to another page
2) The other page invalidates the php session
3) the calling page shows some kind of error / message to the user stating that they have timed out
If however you want to timeout after true user inactivity you need this: Detecting idle time in JavaScript elegantly, however i don't believe these solutions at 100% fool proof (they will break totaly on mobile for instance)
NOW - if you want to use the above link - you WILL NEED ajax - as your current code will not work - basically (and i am not going to write you an AJAX tutorial here) - you need to use javascript to work out when your timeout is reached (using the above SO link) AND THEN hit the server and tell it to invalidate the session (read this tutorial for more information http://www.w3schools.com/ajax/)
Note that you need to decide what to do when a user does not invalidate a session via ajax but refreshes the page - that is to say, a user could block all ajax requests from their browser - meaning that they never self-invalidated the session even if they are inactive - you would however maybe want the server to timeout the session after 3 mins or something? this is all app design stuff.

Timeout for website rather than single webpage

I am working on a website hwere i need to introduce security for reasons, my website automatically signs users out after 10 minutes of inactivity. The behavior is, at about 8 minutes of inactivity, a jquery ui dialog pops up, warning the user of their impending timeout. The user can choose to stay signed in, sign out now, or do nothing and they are forced to sign out at the end of the 10 minutes. I achieve this through a javascript code snippet that timeouts (no mouse/keyboard event) and reset any time the user does what I consider an "activity".
My problem is i can make this thing run for my single webpage but have no clue how to use this for complete domain. I have thought of cookies to achieve this feat as well but not very sure. If someone can suggest me what approaches i shall follow for my task, it will be great possi. bly with code example
Get this timeout script running on my complete domain rather than a single webpage. Possibly using cookies or something else.
I would recommend against javascript and create a complete PHP solution.
This can be achieved simply by giving a user a cookie that expires after 10 minutes on each PHP page. That way, the cookie is renewed with each visit, and if they come back after that ten minutes, the cookie is gone and the system will no longer recognize them.
I would also suggest against sessions, they can get messy easily, and if you want to expand to multiple machines to load balance, it becomes almost impossible to manage. It's not a realistic production tool.
Call this every page - This will check if they already have a cookie, if they do, it will renew it with the same value for ten minutes (60 seconds times ten minutes). You can change the cookie name of 'user' to whatever you want.
if(isset($_COOKIE['user'])){
setcookie('user', $_COOKIE['user'], time()+60*10);
//put your user validation code here to make sure the cookie is real
//then you can put your logged in specific data under it.
}
To authorize a user in the first place, most likely when they login, you can do this:
setcookie('user', $value, time()+60*10);
And if you want to log someone out, you can do this:
setcookie('user', '', 0);
Best of luck!
You can use session and/or cookies for this matter. The way you use them, is that in every page of your website you first check for the cookie/session, and only then proceed. So if your user is logged out once, and attempts to go to another page on the website, he/she will first have to login and only then he can proceed, since the session is no longer available for that user.
Something of this sort -
<?php
if( $this->session->userdata('logged_in') == FALSE )
{
// Login again
}
else
{
// Display the page
}
?>
You can do this by setting their session cookie to expire after 10 minutes. Use session_set_cookie_params() to set the duration of the cookie (first parameter).
session_set_cookie_params(600, '/', 'www.example.com', false, false);
session_start();
Make sure you call it before session_start().
You would then use JavaScript to check the expires parameter of the cookie. If it is getting close to the expired time you then would use that same JavaScript to show them the dialog warning their session is about to expire

Prevent back button after logout

I don't want the user to go back to secured pages by clicking back button after logging out. In my logout code, I am unsetting the sessions and redirecting to login page.But, I think the browser is caching the page so it becomes visible despite the session being destroyed from logout.
I am able to avoid this by not allowing the browser to cache
header("Cache-Control", "no-cache, no-store, must-revalidate")
But this way I am loosing the advantage of Browser Caching.
Please suggest a better way of achieving this. I feel, there must be a way of handling this by javascript client side
Implement this in PHP and not javascript.
At the top of each page, check to see if the user is logged in. If not, they should be redirected to a login page:
<?php
if(!isset($_SESSION['logged_in'])) :
header("Location: login.php");
?>
As you mentioned, on logout, simply unset the logged_in session variable, and destroy the session:
<?php
unset($_SESSION['logged_in']);
session_destroy();
?>
If the user clicks back now, no logged_in session variable will be available, and the page will not load.
I was facing this same problem and spent whole day in figuring out it,
Finally rectified it as follows:
In login validation script if user is authenticated set one session value for instance as follows:
$_SESSION['status']="Active";
And then in User Profile script put following code snippet:
<?php
session_start();
if($_SESSION['status']!="Active")
{
header("location:login.php");
}
?>
What above code does is, only and only if $_SESSION['status'] is set to "Active" then only it will go to user profile , and this session key will be set to "Active" only if user is authenticated... [Mind the negation [' ! '] in above code snippet]
Probably logout code should be as follows:
{
session_start();
session_destroy();
$_SESSION = array();
header("location:login.php");
}
Hope this helps...!!!
Here's an easy solution which I have used in my application.
Add the below code inside script tag in the login HTML page (or whichever page it redirects to after logout)
<script>
history.pushState(null, null, null);
window.addEventListener('popstate', function () {
history.pushState(null, null, null);
});
</script>
It will disable the back button. You will not be able to go back by clicking on the back button.
Note: Not tested on Safari.
I think your only server side option is to disallow caching. This is actually not that bad if you are using a Javascript heavy application as your main HTML might only be a series of JS calls and the Views are then generated on the fly. That way the bulk of the data (JS MVC and core code) is cached but the actual page request isn't.
To add to the comments pasted below I would suggest adding a small AJAX call during load time that fires even for cached pages that goes to your backend and checks the session. If not session is not found it would redirect the user away. This is clientside code and not a secure fix, sure, but looks nicer.
You could get this off your conscience with
A cheap fix if all else fails would be a "Please close this window for security reasons" message on the logged out page. – izb May 9 '12 at 8:36
But like N.B. said
You don't have to disable anything. If they go back, they're served the cached version of the restricted page. If they try to click around it, nothing will work because the appropriate session won't be set. – N.B. May 9 '12 at 7:50
You could insert a condition/function on each restricted page, checking if the appropriate session variable is set or not. This way, you can print 2 versions of the page (one for the valid users, and one redirecting to the login page)
Avoiding the user to go back is not a good reason and most of all not secure at all.
If you test the user's session before every "admin" action made on the website, you should be fine, even if the user hit the back button, sees the cached page and tries something.
The "ties something" will return an error since the session is no longer valid.
Instead, you should focus on having a really secured back office.
Here's an easy and quick solution.
To the login form tag add target="_blank" which displays content in a different window. Then after logout simply close that window and the back button problem (Safari browser) is solved.
Even trying to use the history will not display the page and instead redirect to login page. This is fine for Safari browsers but for others such as Firefox the session_destroy(); takes care of it.
the pages on which you required loged in, use setInterval for every 1000 ms and check wheather user is logged in or not using ajax. if user session is invalid, redirect him to log in page.
Note that although users can't change anything after resetting session data and/or cookie, they still may see usual information accessible to a logged in user as they appeared on the last visit. That is caused by browser caching the page.
You have to be sure to add the header on every page accessible by a logged in user, telling the browser that the data is sensitive and they should not cache the script result for the back button. It is important to add
header("Cache-Control: no-cache, must-revalidate");
Note that those other elements other than the immediate result of the script under this header, will still be cached and you can benefit from it. See that you gradually load parts of your page and tag sensitive data and the main HTML with this header.
As the answer suggests, unsetting the logged_in portion of $_SESSION global variable can achieve logging out, but be aware that first, you don't need to destroy session as mentioned in the PHP's session_destroy() documentation
Note: You do not have to call session_destroy() from usual code. Cleanup $_SESSION array rather than destroying session data.
And second, you better not to destroy the session at all as the next warning on the documentation explains.
Also, unset() is a lazy function; meaning that it won't apply the effect, until next use of the (part of the) variable in question. It is good practice to use assignment for immediate effect in sensitive cases, mostly global variables that may be used in concurrent requests. I suggest you use this instead:
$_SESSION['logged_in'] = null;
and let the garbage collector collects it, at the same time it is not valid as a logged in user.
Finally, to complete the solution, Here are some functions:
<?php
/*
* Check the authenticity of the user
*/
function check_auth()
{
if (empty($_SESSION['logged_in']))
{
header('Location: login.php');
// Immediately exit and send response to the client and do not go furthur in whatever script it is part of.
exit();
}
}
/*
* Logging the user out
*/
function logout()
{
$_SESSION['logged_in'] = null;
// empty($null_variable) is true but isset($null_variable) is also true so using unset too as a safeguard for further codes
unset($_SESSION['logged_in']);
// Note that the script continues running since it may be a part of an ajax request and the rest handled in the client side.
}

auto logout user after # mins of inactivity

i have a client side jquery script that logs the user off after 5 mins of inactivity. The problem is though is the user navigates away without logging out the session stays active. If the user closes the browser shouldnt that destroy the session since sessions stay alive for the duration of the browsers being open or the user logs off?
anywho this is what i have
(function($){
$(document).bind("idle.idleTimer", function(){
document.location = "orders.php?action=logoff&session=timeout";
});
//var minute = 60000; //1 minute is 60,000 miliseconds.
var minute = 300000; //5 minutes
var timeout = minute;
$.idleTimer(timeout);
})(jQuery);
how can i implement a server side if the user navigates away? I was thinking of using cron but then that would be not the right way (im thinking but then maybe im wrong)
i read this post
User Inactivity Logout PHP
and i don't see how the session can still take effect if the user navigates away
Navigating away necessarily doesn't expire the session, its closing the browser that does.
I would implement the check on the server side.
If the session is invalid, you should send down a 400 HTTP status code, which your JS code can use to identify that the user is no longer allowed to use the resource and hence redirect to the login page.
Set cookies expiry values to something that suits your application better.
Sarmen, the easiest way is to use the php session garbage collection to suit your need:
http://www.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime
300s will meet your requirement.
All you need to do is add some code to your orders.php file.
What you need to do is have a few if statements checking for your $_GET variables of action and session.
If both of those requirements are met then you just need to destroy your session with session_destroy();
you can also redirect them to any page if you would like using header();

How to tell the difference between a page refresh and closing a page

I have a web app game and while in the game I want to have it so if a user closes the page or their browser, it will automatically log them out. I tried using the onbeforeunload event attached to the window:
window.onbeforeunload = function() {
// perform logout functions here
}
The problem is, that will also fire if the user refreshes the page. Is there a way I could detect whether or not the user is completely closing the whole page, or just refreshing it?
There is not a detectable difference. To automatically logout a user, you should set an expiration on your cookie storing the login or session information. So if you set it for 1 hour, the user would essentially be logged out after that time since the cookie would be destroyed. If you wanted to postpone this auto logout while they are still interacting with the site, you could reset the expiration of the cookie every time they perform some sort of action (clicking a link, activating an AJAX call, etc). That would mean that they'd be logged out after 1 hour of inactivity as opposed to just 1 hour from login, which sounds more like what you want.
If you set the cookie's expiration to 0, then it will expire it after the session ends. That usually occurs when the user quits their browser entirely. That's another option as well.
As said, you cannot. Even worse, this event have been abandoned by lot of browsers, probably because it have been abused by malicious scripts doing pop-under and such.
A possible workaround is to have an Ajax script "phoning home": if it is silent for some time, the user just abandoned the site (closed page or browser).
Have the onunload event send a request to the server which will cause the session to expire in n seconds (where n is the maximum time for a page reload request to occur, so perhaps 10). Then have the script for the site check to see if that event is scheduled and if so, cancel it. This would give you the behavior you seem to want.
But yeah, I'd recommend simply having the session expire.
If I'm not mistaken Javascript should have a function named something like onWindowClose, maybe try searching for it?
Regarding PHP solutions, I'm not sure if there are any but I suggest you take a quick look into PHP Connection Handling, specifically the connection_aborted() and register_shutdown_function() functions.

Categories