Asked  7 Months ago    Answers:  5   Viewed   28 times

I have heard mixed responses on this topic, so what is a sure fire way to destroy a PHP session?

session_start();
if(isset($_SESSION['foo'])) {
   unset($_SESSION['foo'];
   ...
}
session_destroy();

In the most simple of cases, would this sufficient to truly terminate the session between the user and the server?

 Answers

19

To destroy a session you should take the following steps:

  • delete the session data
  • invalidate the session ID

To do this, I’d use this:

session_start();
// resets the session data for the rest of the runtime
$_SESSION = array();
// sends as Set-Cookie to invalidate the session cookie
if (isset($_COOKIE[session_name()])) { 
    $params = session_get_cookie_params();
    setcookie(session_name(), '', 1, $params['path'], $params['domain'], $params['secure'], isset($params['httponly']));
}
session_destroy();

And to be sure that the session ID is invalid, you should only allow session IDs that were being initiated by your script. So set a flag and check if it is set:

session_start();
if (!isset($_SESSION['CREATED'])) {
    // invalidate old session data and ID
    session_regenerate_id(true);
    $_SESSION['CREATED'] = time();
}

Additionally, you can use this timestamp to swap the session ID periodically to reduce its lifetime:

if (time() - $_SESSION['CREATED'] > ini_get('session.gc_maxlifetime')) {
    session_regenerate_id(true);
    $_SESSION['CREATED'] = time();
}
Wednesday, March 31, 2021
 
themihai
answered 7 Months ago
94

P.S: you can protect your cookies even more by using http_only cookies. For PHP you could read http://ilia.ws/archives/121-httpOnly-cookie-flag-support-in-PHP-5.2.html. I forgot to do for this session example, but did use it for cookie example :(. When you use this your cookies can not be read from JavaScript with most browsers(that support http_only). To use http_only cookie for your session: ini_set("session.cookie_httponly", 1);

What's the difference in PHP between setting a cookie without expiration (meaning it expires as the browser closes) and setting a session variable

They can keep track of the same information, but with cookies(not using session) all information is stored on user/webbrowser which can be stolen by hackers or even altered to provide false information. For simple things you could use cookies, but then again I think you could also use sessions, because when you use cookie you need to transmit more information over the wire.


The internet(HTTP) standard is a stateless protocol(no memory) which has the advantage that it simplifies server design. The internet uses cookie to make it "remember".

Sessions only use cookie to store PHPSESSID inside cookie. Standard the rest of the information is stored on disc which is more secure way to keep state (store sensitive information). You could also encrypt your cookie to do this, but I think sessions is are nice way to do this.

You can override this behaviour and probably should when your website has high traffic to use something like memcached/redis to just store the session information inside memory(Memory is a lot faster than spinning disc to read file because memory also has no moving parts and is very close to CPU). For this to do you need to override session_set_save_handler. It is pretty easy to do with redis. To install redis just type make. Predis is the recommended(popular) redis client library for PHP. To save session information inside redis you could use redis-session-php.

Session

Code

I created a really simple php file to demonstrate sessions.

<?php

session_start();

if (!isset($_SESSION['count'])) {
    $_SESSION['count'] = 0;
}

echo $_SESSION['count']++;

Curl first time saving cookie

I am using Linux Ubuntu below.

alfred@alfred-laptop:~/www/stackoverflow/6717214$ curl http://localhost/stackoverflow/6717214/session.php -v -c cookie
* About to connect() to localhost port 80 (#0)
*   Trying ::1... Connection refused
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /stackoverflow/6717214/session.php HTTP/1.1
> User-Agent: curl/7.21.0 (i686-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18
> Host: localhost
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sat, 16 Jul 2011 12:13:43 GMT
< Server: Apache/2.2.16 (Ubuntu)
< X-Powered-By: PHP/5.3.3-1ubuntu9.3
* Added cookie PHPSESSID="eauo6se9o34oegs57nuhs5u3b7" for domain localhost, path /, expire 0
< Set-Cookie: PHPSESSID=eauo6se9o34oegs57nuhs5u3b7; path=/
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< Vary: Accept-Encoding
< Content-Length: 1
< Content-Type: text/html
< 
* Connection #0 to host localhost left intact
* Closing connection #0
0
  • -v: Make the operation more talkative
  • -c: Write cookies to this file after operation

Next we show output cookie created by our session

alfred@alfred-laptop:~/www/stackoverflow/6717214$ cat cookie 
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This file was generated by libcurl! Edit at your own risk.

localhost   FALSE   /   FALSE   0   PHPSESSID   d5jfijp8515pbhnoe43v4rau97

Standard PHP uses the file-system to store data belonging to session(PHPSESSID).For me the files are located at /var/lib/php5

alfred@alfred-laptop:~/www/stackoverflow/6717214$ php -r "echo session_save_path();"
/var/lib/php5

As you can see it stores that information inside file sess_d5jfijp8515pbhnoe43v4rau97. It is using serialize under the cover to convert object to string.

alfred@alfred-laptop:/var/lib/php5$ sudo cat sess_d5jfijp8515pbhnoe43v4rau97
count|i:1;

I need to sudo because I can standard not read from that location

alfred@alfred-laptop:/var/lib$ sudo ls -la /var/lib/ | grep php5
drwx-wx-wt  2 root          root           4096 2011-07-16 14:16 php5

The read bit has not been set for that directory

Curl second time using saved cookie

alfred@alfred-laptop:~/www/stackoverflow/6717214$ curl -v -b cookie http://localhost/stackoverflow/6717214/session.php
* About to connect() to localhost port 80 (#0)
*   Trying ::1... Connection refused
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /stackoverflow/6717214/session.php HTTP/1.1
> User-Agent: curl/7.21.0 (i686-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18
> Host: localhost
> Accept: */*
> Cookie: PHPSESSID=d5jfijp8515pbhnoe43v4rau97
> 
< HTTP/1.1 200 OK
< Date: Sat, 16 Jul 2011 12:28:59 GMT
< Server: Apache/2.2.16 (Ubuntu)
< X-Powered-By: PHP/5.3.3-1ubuntu9.3
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< Vary: Accept-Encoding
< Content-Length: 1
< Content-Type: text/html
< 
* Connection #0 to host localhost left intact
* Closing connection #0
1
  • -b: Cookie string or file to read cookies from

As you can see we can count without storing any of that information inside cookie. We use the same cookie to remember our state. You can also see that the information on disc has changed to reflect this.

alfred@alfred-laptop:~/www/stackoverflow/6717214$ sudo cat /var/lib/php5/sess_d5jfijp8515pbhnoe43v4rau97
count|i:2;

Cookies

When just using cookies everything is stored on the users computer.

Code

<?php

$counter = 0;

if (isset($_COOKIE['counter'])) {
    $counter = $_COOKIE['counter'] + 1;
}

setCookie("counter", $counter, NULL, NULL, NULL, NULL, TRUE);
echo $counter;

First time with Curl storing cookie

alfred@alfred-laptop:~/www/stackoverflow/6717214$ curl -c cookie -v http://localhost/stackoverflow/6717214/cookie.php
* About to connect() to localhost port 80 (#0)
*   Trying ::1... Connection refused
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /stackoverflow/6717214/cookie.php HTTP/1.1
> User-Agent: curl/7.21.0 (i686-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18
> Host: localhost
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sat, 16 Jul 2011 13:22:03 GMT
< Server: Apache/2.2.16 (Ubuntu)
< X-Powered-By: PHP/5.3.3-1ubuntu9.3
* Added cookie counter="0" for domain localhost, path /stackoverflow/6717214/, expire 0
< Set-Cookie: counter=0; httponly
< Vary: Accept-Encoding
< Content-Length: 1
< Content-Type: text/html
< 
* Connection #0 to host localhost left intact
* Closing connection #0
0

When we output cookie we get:

alfred@alfred-laptop:~/www/stackoverflow/6717214$ cat cookie
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_localhost FALSE   /stackoverflow/6717214/ FALSE   0   counter0

As you can see everything is stored inside the cookie and sent over the wire.

Curl Second time using cookie

alfred@alfred-laptop:~/www/stackoverflow/6717214$ curl -b cookie -c cookie -v htp://localhost/stackoverflow/6717214/cookie.php
* About to connect() to localhost port 80 (#0)
*   Trying ::1... Connection refused
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /stackoverflow/6717214/cookie.php HTTP/1.1
> User-Agent: curl/7.21.0 (i686-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18
> Host: localhost
> Accept: */*
> Cookie: counter=0
> 
< HTTP/1.1 200 OK
< Date: Sat, 16 Jul 2011 13:32:24 GMT
< Server: Apache/2.2.16 (Ubuntu)
< X-Powered-By: PHP/5.3.3-1ubuntu9.3
* Replaced cookie counter="1" for domain localhost, path /stackoverflow/6717214/, expire 0
< Set-Cookie: counter=1; httponly
< Vary: Accept-Encoding
< Content-Length: 1
< Content-Type: text/html
< 
* Connection #0 to host localhost left intact
* Closing connection #0
1
Wednesday, March 31, 2021
 
SilverHorn
answered 7 Months ago
70

You need to unset the session vars. See http://php.net/manual/de/function.session-unset.php

Means, put session_unset() before you destroy the session.

Saturday, May 29, 2021
 
sholsinger
answered 5 Months ago
100

Create a new column in the ci_session table.

ALTER TABLE `yourdatabase`.`ci_sessions` 
ADD COLUMN `userid` VARCHAR(45) NULL  AFTER `user_data` ;

Then in your login function get the id from your login process and before adding the userdata information to the session do:

/* Delete any existing sessions with the current userid session.
Note - a new session has already been generated but doesn't have a value
in the userid column, so won't get deleted. */
$this->db->delete('ci_sessions',array('userid' => $identity));    

// Get the current session and update it with the userid value.
$session_id = $this->session->userdata('session_id');
$this->db->where('session_id', $session_id);
$this->db->update('ci_sessions', array('userid' => $identity));

Where $identity is your userid. That clears any previous sessions and means only one exists at a time.

Saturday, July 31, 2021
 
Exoon
answered 3 Months ago
32

I would like to thank everybody who participated this question, the answer is the following: in reality memcache (not memcached) as session handler supports comma separated servers as the session.save_path, moreover it supports failover. The error mentioned above Session start failed. Original message: session_start(): Server 10.0.10.111 (tcp 11211) failed with: Connection refused (111) had only 8th (Notice) level. In fact engine just informs you about the fact that one of the servers is unavailable (which is logical, as otherwise how will you know?) and then successfully connects to the second server and using it.

So all of the misunderstanding has been caused by weak documentation, memcache/memcached confusions and paranoid (E_ALL) settings of my custom error handler. In the meantime the issue has been resolved by ignoring notices referring to error Connection refused (111) in the session establishing context

Sunday, September 19, 2021
 
Ralph Shillington
answered 1 Month ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :