-
-
Save pete-webpagetech/49bfd623c6821528754c to your computer and use it in GitHub Desktop.
PHP Encrypted Session save Handler with session access class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* | |
* Session class fork from eddmann/SecureSessionHandler.php | |
* SecureSession fork from ezimuel/PHP-Secure-Session | |
* | |
* | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
* | |
* | |
*/ | |
/** | |
* show off @property, @property-read, @property-write | |
* @property mixed $* maps to $_SESSION[*] Set/Get/isset/unset session varibles though Magic Methods | |
* @property-read mixed $* maps to $_SESSION[*] | |
* @property-write mixed $* maps to $_SESSION[*] | |
*/ | |
class Session extends SecureSession { | |
protected $_use_ip=FALSE; | |
public function __construct($useIp=FALSE){ | |
if($useIp==TRUE){ | |
$this->_use_ip=TRUE; | |
} | |
parent::__construct(); | |
} | |
public function start(){ | |
if(session_status() == PHP_SESSION_NONE){ | |
if (session_start()) { | |
return mt_rand(0, 4) === 0 ? $this->refresh() : true; // 1/5 | |
} | |
} | |
return false; | |
} | |
public function refresh(){ | |
return session_regenerate_id(true); | |
} | |
public function forget(){ | |
if (session_status() == PHP_SESSION_NONE) { | |
return false; | |
} | |
return session_destroy(); | |
} | |
public function isValid(){ | |
return ! $this->isExpired() && $this->isFingerprint(); | |
} | |
private function isExpired($ttl = 30){ | |
$last = isset($_SESSION['_last_activity'])? $_SESSION['_last_activity'] : false; | |
if ($last !== false && time() - $last > $ttl * 60) { | |
return true; | |
} | |
$_SESSION['_last_activity'] = time(); | |
return false; | |
} | |
private function isFingerprint(){ | |
$remoteAddress=($this->_use_ip) ? $_SERVER['REMOTE_ADDR'] : FALSE ; | |
$hash = md5( | |
$_SERVER['HTTP_USER_AGENT'] . | |
(inet_ntop(inet_pton($remoteAddress)) & inet_ntop(inet_pton('255.255.0.0'))) | |
); | |
if (isset($_SESSION['_fingerprint'])) { | |
return $_SESSION['_fingerprint'] === $hash; | |
} | |
$_SESSION['_fingerprint'] = $hash; | |
return true; | |
} | |
private function filterVar($value){ | |
$val=FALSE; | |
if(is_string($value)){ | |
$val=filter_var($value, FILTER_SANITIZE_STRING); | |
} | |
elseif(is_int($value)){ | |
$val=filter_var($value, FILTER_SANITIZE_NUMBER_INT); | |
} | |
elseif(is_float($value)){ | |
$val=filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT); | |
} | |
elseif(is_bool($value)){ | |
$val=filter_var($value, FILTER_SANITIZE_STRING); | |
} | |
if($val!=FALSE){ | |
return $val; | |
}else{ | |
return FALSE; | |
} | |
} | |
public function __set($name, $value) { | |
$paramName=(is_string($name))? filter_var($name,FILTER_SANITIZE_STRING): FALSE; | |
$paramValue=$this->filterVar($value); | |
if($paramName!=FALSE){ | |
$_SESSION["$paramName"]=$paramValue; | |
return TRUE; | |
} | |
return FALSE; | |
} | |
public function __get($name) { | |
$paramName=(is_string($name))? filter_var($name,FILTER_SANITIZE_STRING): FALSE; | |
if($paramName!=FALSE){ | |
if(isset($_SESSION[$paramName])){ | |
return $_SESSION[$paramName]; | |
} | |
} | |
return FALSE; | |
} | |
public function __isset($name) { | |
$paramName=(is_string($name))? filter_var($name,FILTER_SANITIZE_STRING): FALSE; | |
if($paramName!=FALSE){ | |
return isset($_SESSION[$paramName]); | |
} | |
return FALSE; | |
} | |
public function __unset($name) { | |
$paramName=(is_string($name))? filter_var($name,FILTER_SANITIZE_STRING): FALSE; | |
if($paramName!=FALSE){ | |
if(isset($_SESSION[$paramName])){ | |
unset($_SESSION[$paramName]); | |
return TRUE; | |
} | |
} | |
return FALSE; | |
} | |
} | |
/** | |
* ------------------------------------------------ | |
* Encrypt PHP session data using files | |
* ------------------------------------------------ | |
* The encryption is built using mcrypt extension | |
* and the randomness is managed by openssl | |
* The default encryption algorithm is AES (Rijndael-128) | |
* and we use CBC+HMAC (Encrypt-then-mac) with SHA-256 | |
* | |
* @author Enrico Zimuel (enrico@zimuel.it) | |
* @copyright GNU General Public License | |
*/ | |
class SecureSession { | |
/** | |
* Encryption algorithm | |
* | |
* @var string | |
*/ | |
protected $_algo= MCRYPT_RIJNDAEL_128; | |
/** | |
* Key for encryption/decryption | |
* | |
* @var string | |
*/ | |
protected $_key; | |
/** | |
* Key for HMAC authentication | |
* | |
* @var string | |
*/ | |
protected $_auth; | |
/** | |
* Path of the session file | |
* | |
* @var string | |
*/ | |
protected $_path; | |
/** | |
* Session name (optional) | |
* | |
* @var string | |
*/ | |
protected $_name; | |
/** | |
* Size of the IV vector for encryption | |
* | |
* @var integer | |
*/ | |
protected $_ivSize; | |
/** | |
* Cookie variable name of the encryption + auth key | |
* | |
* @var string | |
*/ | |
protected $_keyName; | |
/** | |
* Generate a random key using openssl | |
* fallback to mcrypt_create_iv | |
* | |
* @param integer $length | |
* @return string | |
*/ | |
protected function _randomKey($length=32) { | |
if(function_exists('openssl_random_pseudo_bytes')) { | |
$rnd = openssl_random_pseudo_bytes($length, $strong); | |
if ($strong === true) { | |
return $rnd; | |
} | |
} | |
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); | |
} | |
/** | |
* Constructor | |
*/ | |
public function __construct() | |
{ | |
session_set_save_handler( | |
array($this, "open"), | |
array($this, "close"), | |
array($this, "read"), | |
array($this, "write"), | |
array($this, "destroy"), | |
array($this, "gc") | |
); | |
if (!extension_loaded('mcrypt')) { | |
throw new Exception("The SecureSession class needs the Mcrypt PHP extension, please install it."); | |
} | |
$sessionPath = sys_get_temp_dir(); | |
session_save_path($sessionPath); | |
ini_set('session.gc_probability', 1); | |
} | |
/** | |
* Open the session | |
* | |
* @param string $save_path | |
* @param string $session_name | |
* @return bool | |
*/ | |
public function open($save_path, $session_name) | |
{ | |
$this->_path = $save_path.'/'; | |
$this->_name = $session_name; | |
$this->_keyName = "KEY_$session_name"; | |
$this->_ivSize = mcrypt_get_iv_size($this->_algo, MCRYPT_MODE_CBC); | |
if (empty($_COOKIE[$this->_keyName]) || strpos($_COOKIE[$this->_keyName],':')===false) { | |
$keyLength = mcrypt_get_key_size($this->_algo, MCRYPT_MODE_CBC); | |
$this->_key = self::_randomKey($keyLength); | |
$this->_auth = self::_randomKey(32); | |
$cookie_param = session_get_cookie_params(); | |
setcookie( | |
$this->_keyName, | |
base64_encode($this->_key) . ':' . base64_encode($this->_auth), | |
// if session cookie lifetime > 0 then add to current time; otherwise leave it as zero, honoring zero's special meaning: expire at browser close. | |
($cookie_param['lifetime'] > 0) ? time() + $cookie_param['lifetime'] : 0, | |
$cookie_param['path'], | |
$cookie_param['domain'], | |
$cookie_param['secure'], | |
$cookie_param['httponly'] | |
); | |
} else { | |
list ($this->_key, $this->_auth) = explode (':',$_COOKIE[$this->_keyName]); | |
$this->_key = base64_decode($this->_key); | |
$this->_auth = base64_decode($this->_auth); | |
} | |
return true; | |
} | |
/** | |
* Close the session | |
* | |
* @return bool | |
*/ | |
public function close() | |
{ | |
return true; | |
} | |
/** | |
* Read and decrypt the session | |
* | |
* @param integer $id | |
* @return string | |
*/ | |
public function read($id) | |
{ | |
$sess_file = $this->_path.$this->_name."_$id"; | |
if (!file_exists($sess_file)) { | |
return false; | |
} | |
$data = file_get_contents($sess_file); | |
list($hmac, $iv, $encrypted)= explode(':',$data); | |
$iv = base64_decode($iv); | |
$encrypted = base64_decode($encrypted); | |
$newHmac = hash_hmac('sha256', $iv . $this->_algo . $encrypted, $this->_auth); | |
if ($hmac !== $newHmac) { | |
return false; | |
} | |
$decrypt = mcrypt_decrypt( | |
$this->_algo, | |
$this->_key, | |
$encrypted, | |
MCRYPT_MODE_CBC, | |
$iv | |
); | |
return rtrim($decrypt, "\0"); | |
} | |
/** | |
* Encrypt and write the session | |
* | |
* @param integer $id | |
* @param string $data | |
* @return bool | |
*/ | |
public function write($id, $data) | |
{ | |
$sess_file = $this->_path . $this->_name . "_$id"; | |
$iv = mcrypt_create_iv($this->_ivSize, MCRYPT_DEV_URANDOM); | |
$encrypted = mcrypt_encrypt( | |
$this->_algo, | |
$this->_key, | |
$data, | |
MCRYPT_MODE_CBC, | |
$iv | |
); | |
$hmac = hash_hmac('sha256', $iv . $this->_algo . $encrypted, $this->_auth); | |
$bytes = file_put_contents($sess_file, $hmac . ':' . base64_encode($iv) . ':' . base64_encode($encrypted)); | |
return ($bytes !== false); | |
} | |
/** | |
* Destoroy the session | |
* | |
* @param int $id | |
* @return bool | |
*/ | |
public function destroy($id) | |
{ | |
$sess_file = $this->_path . $this->_name . "_$id"; | |
setcookie ($this->_keyName, '', time() - 3600); | |
return(@unlink($sess_file)); | |
} | |
/** | |
* Garbage Collector | |
* | |
* @param int $max | |
* @return bool | |
*/ | |
public function gc($max) | |
{ | |
foreach (glob($this->_path . $this->_name . '_*') as $filename) { | |
if (filemtime($filename) + $max < time()) { | |
@unlink($filename); | |
} | |
} | |
return true; | |
} | |
} | |
/* | |
* Usage... | |
*/ | |
//start the session | |
$session = new Session(); | |
$session->start(); | |
//check if current session is expired (30Min default). | |
if ( ! $session->isValid()) { | |
$session->forget(); | |
} | |
//make new session var... uses set magic method | |
$session->foo="Hello World"; | |
//get an already set session var... uses get magic method | |
echo $session->foo; | |
//check if session var is set already... uses isset magic method | |
if(isset($session->foo)){ | |
//remove an already set session var... uses unset magic method | |
unset($session->foo); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment