Asked  7 Months ago    Answers:  5   Viewed   37 times

When I call session_start() or session_regenerate_id(), PHP generates what appears to be a random string for the session ID. What I want to know is, is it just a random sequence of characters, or is it like the uniqid() function?

Because if it's just random characters, couldn't you theoretically run into a conflict? If User A logged in and then User B logged in and, though highly unlikely, User B generated the same session ID, then User B would end up accessing User A's account.

Even if PHP checks to see if a session with the same ID already exists and, if so, regenerates an ID again... I don't think I want a system that EVER produces the same ID twice, even after garbage collection -- maybe I want to store a table of them and check against them for possible hijacking or whatever.

If it isn't unique, how should I go about enforcing uniqueness? I'd rather implement it using PHP configuration than in every script I make. Nice thing about PHP sessions is not worrying about the technical details behind the scenes.

 Answers

21

If you want to know how PHP generates a session ID by default check out the source code on Github. It is certainly not random and is based on a hash (default: md5) of these ingredients (see line 310 of code snippet):

  1. IP address of the client
  2. Current time
  3. PHP Linear Congruence Generator - a pseudo random number generator (PRNG)
  4. OS-specific random source - if the OS has a random source available (e.g. /dev/urandom)

If the OS has a random source available then strength of the generated ID for the purpose of being a session ID is high (/dev/urandom and other OS random sources are (usually) cryptographically secure PRNGs). If however it does not then it is satisfactory.

The goal with session identification generation is to:

  1. minimise the probability of generating two session IDs with the same value
  2. make it very challenging computationally to generate random keys and hit an in use one.

This is achieved by PHP's approach to session generation.

You cannot absolutely guarantee uniqueness, but the probabilities are so low of hitting the same hash twice that it is, generally speaking, not worth worrying about.

Wednesday, March 31, 2021
 
Slinky
answered 7 Months ago
75

The concept is storing persistent data across page loads for a web visitor. Cookies store it directly on the client. Sessions use a cookie as a key of sorts, to associate with the data that is stored on the server side.

It is preferred to use sessions because the actual values are hidden from the client, and you control when the data expires and becomes invalid. If it was all based on cookies, a user (or hacker) could manipulate their cookie data and then play requests to your site.

Edit: I don't think there is any advantage to using cookies, other than simplicity. Look at it this way... Does the user have any reason to know their ID#? Typically I would say no, the user has no need for this information. Giving out information should be limited on a need to know basis. What if the user changes his cookie to have a different ID, how will your application respond? It's a security risk.

Before sessions were all the rage, I basically had my own implementation. I stored a unique cookie value on the client, and stored my persistent data in the database along with that cookie value. Then on page requests I matched up those values and had my persistent data without letting the client control what that was.

Wednesday, March 31, 2021
 
Gigamegs
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
34

Problem solved. The thing that i did was to empty the session and regenerate the id, then destroy it. I don't fully understand the problem, but it kinda does the job:

<?php    
session_start();

if(isset($_SESSION['id_client']) &&  isset($_POST['ok'])){
    $_SESSION=array();
    session_regenerate_id(); 
    session_destroy();
    echo 1;
}
?>
Saturday, May 29, 2021
 
Aamir
answered 5 Months ago
74

Try

<?php
    if(!isset($_SESSION)) 
    { 
        session_start(); 
    } 
?>
Tuesday, June 8, 2021
 
KouiK
answered 5 Months 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 :