Session 函数
在线手册:中文 英文
PHP手册

session_destroy

(PHP 4, PHP 5)

session_destroyDestroys all data registered to a session

说明

bool session_destroy ( void )

session_destroy() destroys all of the data associated with the current session. It does not unset any of the global variables associated with the session, or unset the session cookie. To use the session variables again, session_start() has to be called.

In order to kill the session altogether, like to log the user out, the session id must also be unset. If a cookie is used to propagate the session id (default behavior), then the session cookie must be deleted. setcookie() may be used for that.

返回值

成功时返回 TRUE, 或者在失败时返回 FALSE.

范例

Example #1 Destroying a session with $_SESSION

<?php
// Initialize the session.
// If you are using session_name("something"), don't forget it now!
session_start();

// Unset all of the session variables.
$_SESSION = array();

// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
    
$params session_get_cookie_params();
    
setcookie(session_name(), ''time() - 42000,
        
$params["path"], $params["domain"],
        
$params["secure"], $params["httponly"]
    );
}

// Finally, destroy the session.
session_destroy();
?>

注释

Note:

Only use session_unset() for older deprecated code that does not use $_SESSION.

参见


Session 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: Destroys all data registered to a session

用户评论:

john at host89 dot net (22-Jan-2010 08:11)

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.

yesmarklapointe at hotmail dot com (16-Sep-2008 06:16)

I ran an experiment. Firefox3 and IE7 both behave the same on my machine. The following statements clear out the variables immediately:

session_unset()
$_SESSION = array()
unset($_SESSION['whatever'])

But if you are intent upon using session_destroy(), know that it only empties out the variables when the page is reloaded or redirected to some other page. As long as it's the same page, the variables are still usable after invoking session_destroy().

elbowni (27-Aug-2008 10:23)

If you want to remove all variables from session and change SID first use

session_regenerate_id();
session_destroy();

if you do destroy first then regenerate_id your SID will not change

iam4webwork at hotmail dot com (17-Jul-2008 09:19)

<?php
session_name
("PeekABook");
/**
   *
   *  Assuming that we resume a session already underway
   *  with a specified session name, over-riding
   *  the default provided in php.ini: session.name
   *
**/ 

session_start();

/**
   * If you only wish to nullify all of the session variables.
   *
**/
$_SESSION = array();

/**
   * read and save session name to later void session
   * cookie
   *
**/
$session_name = session_name();  

/**
  * destroy session data.
  * no need to use session_unset() in PHP5
**/
session_destroy();

/**
   * If you wish to kill the session, then you must
   * delete the  session cookie.
   * An http request is needed to effectively
   * set the cookie to permanent inactive status;
   * only the browser can remove the cookie.
   *
**/

if ( isset( $_COOKIE[ $session_name ] ) ) {
    if (
setcookie(session_name(), '', time()-3600, '/') ) {
       
header("Location: http://localhost/some_other_page.php");
        exit();   
    }
    else
    {
       
// setcookie() fails when there is output sent prior to calling this function.
   
}
}

?>

james at dunmore dot me dot uk (23-Jun-2008 04:25)

If you are using a custom save handler (i.e. calling session_set_save_handler ) - like you would for DB based session handling. If you call session_destroy, followed by session_start, you will get an error.

You need to re-call session_set_save_handler with the lines you previously did (e.g.
session_set_save_handler('mysql_session_write_func') )

ale at alejandrolapeyre dot com dot ar (15-Jun-2008 12:16)

Example #1 fails to delete the session cookie if the session COOKIE is not set but a session is started (as the example does)

To delete the session cookie ALWAYS, change the line:

if (isset($_COOKIE[session_name()])) {

to:

if (session_id != "" || isset($_COOKIE[session_name()]))

administrator at anorhack dot com (01-Aug-2007 03:34)

Destroying  a session from a background job

I have a thief-protection system that compares country codes from login IPs via whois. This has to run in the background as it is way too processor-hungry to be run in the browser.

What I needed was a way to destroy the web session from the background job. For some reason, a background session_destroy APPEARS to work, but doesnt't actually destroy the web session.

There is a work around, I set the username to NULL and the web code picks up on that, bouncing the user (thief) to a "gotcha" page where his IP is logged.

Yes I know its nasty and dirty, but surprisingly it works.

$sid = the session_id() of the suspicious web session, passed in $argv to the background job

The trick is to "stuff" the $_GET array with the sid, then the session_start in the background job picks this value up (as if it were a genuine trans-sid type thing...?PHPSESSID=blah) and "connects to" the web session. All $_SESSION variable can be viewed (and CHANGED , which is how this kludge works) but for some reason (that no doubt someone will illuminate) they can't be unset...setting the particular variable to NULL works well though:

 
$_GET[session_name()]=$sid;
session_start();
// prove we are getting the web session data
foreach($_SESSION as $k => $v) echo($k."=".$v);
// now kill the thief
$_SESSION['username']=NULL;
//web session variable now NULL - honestly!

wade at defianceinteractive dot com (12-Feb-2007 07:59)

You should also be careful when you destroy a session. I believe a previous user posted something similar to this but didn't emphasize this point.

If you are creating a new session, but want to make sure that  there are currently no sessions active by doing session_destroy(); make sure you start the session again using session_start(); or else your session data will not register properly.

Colin (07-Feb-2007 09:52)

Note that when you are using a custom session handler, session_destroy will cause a fatal error if you have set the session destroy function used by session_set_save_handler to private.

Example:
Fatal error: Call to private method Session::sessDestroy()

where sessDestroy was the function I specified in the 5th parameter of session_set_save_handler.

Even though it isn't all that desirable, the simple solution is to set sessDestroy to public.

r dot swets at guidance dot nl (21-Dec-2006 08:59)

Bothering with the timestamp can always give troubles. A lot better is forcing the sessionid to be regenrerated. A trick to destroy the session completly is actually restarting the session, like someone closed and reopened his browser. This will fix the whole authority problem and browser cookie deletion problem quite more easy, and it gives cleaner code without having to clean the $_SESSION array.

I would suggest the following function session_restart();

<?php

session_start
();

// Some simple code etc etc
$requested_logout = true;

if (
$requested_logout) {
   
session_restart();
}

// Now the session_id will be different every browser refresh
print(session_id());

function
session_restart()
{
    if (
session_name()=='') {
       
// Session not started yet
       
session_start();
    }
    else {
       
// Session was started, so destroy
       
session_destroy();

       
// But we do want a session started for the next request
       
session_start();
       
session_regenerate_id();

       
// PHP < 4.3.3, since it does not put
       
setcookie(session_name(), session_id());
    }
}

?>

NOTE: session_restart() acts like session_start(), so no output must be written before its called.

rob a.t. mobius d.o.t. ph (02-Dec-2006 10:02)

I was experiencing problems with "sess_deleted" files and tracked it down to:

    setcookie(session_name(), '', time()-42000, '/');

When "setcookie" is passed an empty value (ie, ''), it changes the value to the string "deleted" and sets the date to exactly one year and one second in the past, ignoring the expiration parameter.*

So, I'm guessing that if a client machine has its time set to more than a year in the past or if the browser is somehow broken, then a site visitor could potentially send a PHPSESSID with a value of "deleted".  This will cause PHP to create a "sess_deleted" file in the sessions directory.

In my case, I was seeing several incidents per minute, with each user clobbering the other's session data causing all kinds of security and identity issues.  Two changes seemed to have solved the problem:

1) Use session_id() in place of '' in setcookie, as well as pick a date that's far in the past (in this case Jan 1, 1970, 8:00:01AM):

    setcookie(session_name(), session_id(), 1, '/');

2) Use session_regenerate_id() when logging a user in or otherwise changing their authority level.

Hope this helps somebody.

Rob

* Here is the relevant code in head.c:

    if (value && value_len == 0) {
        /*                                                                                                                                                                                                      
         * MSIE doesn't delete a cookie when you set it to a null value                                                                                                                                         
         * so in order to force cookies to be deleted, even on MSIE, we                                                                                                                                         
         * pick an expiry date 1 year and 1 second in the past                                                                                                                                                  
         */
        time_t t = time(NULL) - 31536001;
        dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, t, 0 TSRMLS_CC);
        sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);

markus at fischer dot name (16-Mar-2005 09:09)

Note that there's a bug with custom session handlers and when you want to start a session again after you have called session_destroy.

session_destroy disables the custom session_handler and this a call to session_start after it will fail with "Failed to initialize storage module".

See http://bugs.php.net/32330 for more information and a workaround.

Johan (20-Nov-2004 02:00)

Remember that session_destroy() does not unset $_SESSION at the moment it is executed.  $_SESSION is unset when the current script has stopped running.

thomas at uninet dot se (07-Oct-2004 04:25)

I did encounter a minor problem when I tried to remove the physical file that stores the session. The problem was that my working directory wasn't on the same drive as my PHP installation (yes, I used Windows).

So I used the PHP_BINDIR to start at the same place as PHP does and then change directory to the place that was specified in PHP.INI. This makes it transparent to relative paths in session.save_path.

<?php
function DeleteSessionID($sessionid) {
 
$orgpath = getcwd();
 
chdir(PHP_BINDIR);
 
chdir(session_save_path());
 
$path = realpath(getcwd()).'/';
  if(
file_exists($path.'sess_'.$sessionid)) {
   
// Delete it here
   
unlink($path.'sess_'.$sessionid);
  } else {
   
// File not found
 
}
 
chdir($orgpath);
}

?>

The final chdir($orgpath) is just to restore the working directory as it were before .

powerlord at spamless dot vgmusic dot com (19-Nov-2002 07:41)

This code might be a bit better for expiring session cookies, in case your domain, path, and/or secure session cookie settings are changed.

    $CookieInfo = session_get_cookie_params();
    if ( (empty($CookieInfo['domain'])) && (empty($CookieInfo['secure'])) ) {
        setcookie(session_name(), '', time()-3600, $CookieInfo['path']);
    } elseif (empty($CookieInfo['secure'])) {
        setcookie(session_name(), '', time()-3600, $CookieInfo['path'], $CookieInfo['domain']);
    } else {
        setcookie(session_name(), '', time()-3600, $CookieInfo['path'], $CookieInfo['domain'], $CookieInfo['secure']);
    }
    unset($_COOKIE[session_name()]);
    session_destroy();