note 95809 deleted from function.session-destroy by googleguy
| From: | googleguy@php.net | Date: | Fri, 14 Sep 2012 05:17:43 +0000 |
| Subject: | note 95809 deleted from function.session-destroy by googleguy | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-190743@lists.php.net to get a copy of this message | ||
Note Submitter: john at host89 dot net
----
Hello all,
While working on a fully customized session management system I decided to add the ability to force
a user from their session while within another administrative session. (Basically, as an admin I
would see currently active sessions and then have the choice to end them immediately.) I had already
written a decently secure session tracking and theft-prevention system (An independent session key
is created and then changed every 5 pages/requests. Even AJAX calls use the key.) I have posted that
code on another page here at PHP.net.
The solution I arrived at was to record session IDs as users log in (If a session ID changes the
user is forced to login again - session key changes frequently instead) and then tie the entries to
their user id, from which I could get their username, name, e-mail, etc. A final part is recording
the time that their session ID is recorded so that a garbage collector could go through and delete
old entries in the database. (IDs are recorded in a MySQL database.)
The code on the login page looks something like this, and is run well after the session has started
and their credentials have been verified:
<?php
# Quick! Record their session information so they can be off kicked by demand later. :-D
$session_id=session_id();
$savsessionquery="INSERT INTO admin_users_sessions (user_id, session_id) VALUES
('".$userid."', '".$session_id."') ON DUPLICATE KEY UPDATE
session_id='".$session_id."'";
$savesessionresult=mysql_query($savsessionquery, $sql);
# And we won't care if it don't work. :-)
?>
That last comment is because if the insert fails, then that user is safe from kicking during their
active session. (However, if they click "Home" it re-runs through the login.php file which
will pick up on a bad password/disallowed login and kick them out via logout.php which unsets the
cookie and variables and destroys the session.)
The table has 4 columns: id, user_id, session_id, and timestamp. id is an AUTO_INCREMENT (so
it's not specifically inserted) and TIMESTAMP is an AUTO-UPDATE (and so it also is not
specifically inserted).
The code that actually kicks them out while maintaining the administrative session is as follows
($_POST['kickid'] is passed from the page where the user can pick the session to kill):
<?php
session_cache_limiter('nocache');
require('authheader.php');
$permissiontocheck="permission5";
require('permissioncheck.php');
$kickid=$_POST['kickid'];
# Alright. Save the current session stuff so we can resume it at the end.
$realsessionid=session_id();
# Look up the session ID we're kicking
$query="SELECT session_id FROM admin_users_sessions WHERE
id='".$kickid."'";
$result=mysql_query($query, $sql);
if (!$result || mysql_num_rows($result)!=1)
{
# No result or too many matches
$_SESSION['returnstatus']=2;
$_SESSION['returnmessage']="Invalid session selection. Please try again.";
header ('Location: forcelogout.php');
exit;
}
$array=mysql_fetch_row($result);
$kicksessionid=$array[0];
# Ok. End the current session and start one up with the ID being kicked.
session_commit();
session_id($kicksessionid);
session_start();
# Now we're in. Destroy some stuff and then get out.
$_SESSION = array();
$_SESSION['loggedin']=false;
session_destroy();
session_commit();
# Sweet. Now we re-load our current session and head back celebrating.
session_id($realsessionid);
session_start();
$_SESSION['returnstatus']=1;
$_SESSION['returnmessage']="Session successfully destroyed";
header ('Location: forcelogout.php');
exit;
?>
authheader.php and permissioncheck.php are both portions of the session management system that this
page runs under. permission5 is the required permission to kick a user from their session.
There you go! Dig in and I hope somebody can use this little tid-bit of code.