carlos1993

SESSION SYSTEM

Jul 3rd, 2013
1,072
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2. /*
  3.  *
  4.  * Author: Carlos Arturo Alaniz
  5.  * Contact info: caag1993@gmail.com; @alaniz93;  caag1993.wordpress.com
  6.  * Last Modified date: 06 /03 /2013
  7.  *
  8.  * Description:
  9.  *  This class replaces the standard php session managment system
  10.  *  it uses a Mysql Database to stor the session info
  11.  *
  12.  *  The data encryopptuion can be turned off by passing a NULL encription
  13.  *  key, the cookies and session can be set to be permanent by passing a
  14.  *  true value to the start session method.
  15.  *  
  16.  *  It requieres a PDO object to stablish the connection to the DB
  17.  *  it also implements 2 very basic security checks to prevent session
  18.  *  related attacks
  19.  *  it store the SERVER_USER_AGENT with every newly opened session to be
  20.  *  later compared, it also stores a cookie counter on the client side and
  21.  *  session counter on the server side both of them must be syncronized
  22.  *  the data its encrypted with a private key and it sets the php.ini
  23.  *  file to a secure configuration.
  24.  *
  25.  */
  26.  
  27. class _session {
  28.  
  29.     private $key = NULL;
  30.     private $permanent = FALSE;
  31.     private $lifetime = 0;
  32.  
  33.     public function __construct(&$connecion_settings, $key = NULL) {
  34.         $this->key = $key;
  35.         $this->pdo = $connecion_settings;
  36.         //set our new session handler
  37.         session_set_save_handler(
  38.                 array($this, 'open'), array($this, 'close'), array($this, 'read'), array($this, 'write'), array($this, 'destroy'), array($this, 'gc')
  39.         );
  40.         //Set php.in to secure setting.
  41.         //This will tell PHP not to include the identifier in the URL, and not to read the URL for identifiers.
  42.         if (ini_get('session.use_trans_sid'))
  43.             ini_set('session.use_trans_sid', 0);
  44.  
  45.         //This will tell PHP to never use URLs with session identifiers.
  46.         if (!ini_get('session.use_only_cookies'))
  47.             ini_set('session.use_only_cookies', 1);
  48.         //Using a strong session hash identifier
  49.         //PHP <= 5.3
  50.         // ini_set('session.hash_function', 1);
  51.         // PHP > 5.3
  52.         ini_set('session.hash_function', 'sha256');
  53.  
  54.         // Send a strong hash
  55.         ini_set('session.hash_bits_per_character', 5);
  56.     }
  57.  
  58.     public function start_session($sessionName = NULL, $permanent = FALSE) {
  59.         if ($permanent) {
  60.             $this->permanent = $permanent;
  61.             $this->lifetime = time() + 86400 * 365 * 2; //2 years
  62.             session_set_cookie_params($this->lifetime);
  63.         }
  64.         if ($sessionName != NULL)
  65.             session_name($sessionName);
  66.         session_start();
  67.         if (!isset($_SESSION['_userAgent']))
  68.             $_SESSION['_userAgent'] = $_SERVER['HTTP_USER_AGENT'];
  69.         if (!isset($_SESSION['_counter'])) {
  70.             $_SESSION['_counter'] = 0;
  71.             setcookie("sessionCounter", "", time() - 7200); //unset cookie
  72.             setcookie('sessionCounter', 0, $this->lifetime, '/', NULL, NULL, 1);
  73.         }
  74.     }
  75.  
  76.     private function updateCounter() {
  77.         $cookieCount = $_COOKIE['sessionCounter'] + 1;
  78.         $_SESSION['_counter'] += 1;
  79.         setcookie("sessionCounter", "", time() - 7200); //unset cookie
  80.         setcookie('sessionCounter', $cookieCount, $this->lifetime, '/', NULL, NULL, 1); //set new value
  81.     }
  82.  
  83.     /*
  84.       //This function implements some basic sessions security checks
  85.       //it checks for anychange in the user agent variable and the one stored in the session
  86.       //it implements a counter on the server side and one on the client side
  87.       //both of them must be the same.
  88.      */
  89.  
  90.     public function securityCheck() {
  91.         $this->updateCounter();
  92.         if (($_SESSION['_userAgent'] != $_SERVER['HTTP_USER_AGENT']) || ($_SESSION['_counter'] != ($_COOKIE['sessionCounter'] + 1))
  93.         ) {
  94.             session_destroy();
  95.             session_write_close();
  96.             //Prompt for password or do something
  97.             //echo "DUH!";
  98.         }
  99.         // else
  100.         // echo "wereGood";
  101.     }
  102.  
  103.     public function open() {
  104.         //This should be a contructor but the connection 'open'
  105.         //settings are in the $connetion variable
  106.         return 0;
  107.     }
  108.  
  109.     public function close() {
  110.         return session_write_close();
  111.     }
  112.  
  113.     public function read($sessionId) {
  114.         $qry = "SELECT data
  115.                FROM sessions
  116.                WHERE id = :id";
  117.  
  118.         //We want to only prepare the statement once
  119.         if (!isset($this->rStatement)) {
  120.             $this->rStatement = $this->pdo->prepare($qry);
  121.         }
  122.  
  123.         $this->rStatement->bindParam(':id', $sessionId, PDO::PARAM_INT);
  124.  
  125.         if ($this->rStatement->execute()) {
  126.             $row = $this->rStatement->fetch(PDO::FETCH_ASSOC);
  127.             if ($this->key != NULL)
  128.                 return $this->decrypt($row['data']);
  129.             else
  130.                 return $row['data'];
  131.         }
  132.         else {
  133.             return false;
  134.         }
  135.     }
  136.  
  137.     public function write($sessionId, $data) {
  138.         if ($this->key != NULL)
  139.             $data = $this->encrypt($data);
  140.  
  141.         $qry = "REPLACE INTO sessions (id, set_time, data, permanent) VALUES (:id, :time, :data, :permanent)";
  142.         $time = time();
  143.  
  144.         //We want to only prepare the statement once
  145.         if (!isset($this->wStatement)) {
  146.             $this->wStatement = $this->pdo->prepare($qry);
  147.         }
  148.         $this->wStatement->bindParam(':id', $sessionId, PDO::PARAM_STR);
  149.         $this->wStatement->bindParam(':time', $time, PDO::PARAM_INT);
  150.         $this->wStatement->bindParam(':data', $data, PDO::PARAM_STR);
  151.         $this->wStatement->bindParam(':permanent', $this->permanent, PDO::PARAM_BOOL);
  152.         if ($this->wStatement->execute()) {
  153.             return true;
  154.         } else {
  155.             echo "error";
  156.             return false;
  157.         }
  158.     }
  159.  
  160.     public function destroy($sessionId) {
  161.         $qry = "DELETE FROM sessions WHERE id = :id";
  162.         //We want to only prepare the statement once
  163.         if (!isset($this->dStatement)) {
  164.             $this->dStatement = $this->pdo->prepare($qry);
  165.         }
  166.         $this->dStatement->bindParam(':id', $sessionId, PDO::PARAM_INT);
  167.         if ($this->dStatement->execute()) {
  168.             unset($_SESSION);   //unset session variables
  169.             setcookie("sessionCounter", "sdf", time() - 7200); //unset cookie
  170.             return true;
  171.         } else {
  172.             return false;
  173.         }
  174.     }
  175.  
  176.     public function gc($max) {
  177.         $qry = "DELETE FROM sessions WHERE set_time < :max AND permanent = 0";
  178.  
  179.         //We want to only prepare the statement once
  180.         if (!isset($this->gcStatement)) {
  181.             $this->gcStatement = $this->pdo->prepare($qry);
  182.         }
  183.         $this->gcStatement->bindParam(':max', $max, PDO::PARAM_INT);
  184.         if ($this->gcStatement->execute()) {
  185.             return 'true';
  186.         } else {
  187.             return false;
  188.         }
  189.     }
  190.  
  191.     private function encrypt($data) {
  192.         $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
  193.         $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
  194.         $en = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->key, $data, MCRYPT_MODE_ECB, $iv));
  195.         return $en;
  196.     }
  197.  
  198.     private function decrypt($data) {
  199.         $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
  200.         $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
  201.         $des = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->key, base64_decode($data), MCRYPT_MODE_ECB, $iv);
  202.         return $des;
  203.     }
  204.  
  205. }
  206.  
  207. ?>
RAW Paste Data