(PHP 5 >= 5.4.0, PHP 7)
SessionHandler это специальный класс, который может использоваться для
дополнения внутреннего обработчика сессий PHP путем создания дочерних классов от этого.
Существует семь методов, которые являются обертками над семью внутренними обработчиками хранения
данных сессии (open
, close
, read
,
write
, destroy
, gc
и
create_sid
). По умолчанию этот класс оборачивает все внутренние
обработчики хранения сессии, определенные в опции конфигурации session.save_handler.
Эта опция по умолчанию имеет значение files
.
Другие внутренние обработчики сессий предоставляются PHP-расширениями, такими как
SQLite (sqlite
), Memcache (memcache
)
и Memcached (memcached
).
Экземпляр класса SessionHandler может устанавливаться в качестве обработчика сессии посредством вызова функции session_set_save_handler(). В этом случае он станет оберткой существующего внутреннего обработчика. Классы, расширяющие SessionHandler позволят переопределить методы обработчика сессии или перехватить/отфильтровать их путем вызова родительских методов-оберток внутреннего обработчика сессий PHP.
Это позволит вам, к примеру, перехватить методы read
и
write
для шифровки/дешифровки данных сессии и передачи
результата родительскому классу и от него. Или, к примеру, вы можете полностью
переопределить такой метод как callback-функция сборщика мусора (gc
).
Так как SessionHandler является оберткой над стандартным внутренним обработчиком сессии, то пример, приведенный выше про шифровку данных может быть применен к любому внутреннему обработчику сессии даже без понимания внутреннего устройства процесса работы сессии.
Для использования этого класса, во-первых, установите обработчик, который вы хотите дополнить используя session.save_handler. Далее передайте экземпляр класса SessionHandler или одного из классов, расширяющих его функции session_set_save_handler().
Обратите внимание, что методы этого класса предназначены для внутреннего вызова из PHP. Вызывать их из своего кода не нужно. Дополнительную информацию о работе сессии можно узнать из описания функции session_set_save_handler().
Этот класс предназначен для расширения текущего внутреннего обработчика сессии PHP. При этом, если вам нужно написать собственный обработчик, то необходимо написать собственную реализацию интерфейса SessionHandlerInterface вместо расширения класса SessionHandler.
Пример #1 Использвание SessionHandler для того, чтобы добавить шифровку данных ко внутреннему обработчику сессий PHP.
<?php
/**
* расшифровать данные, используя алгоритм AES 256
*
* @param data $edata
* @param string $password
* @return расшифрованные данные
*/
function decrypt($edata, $password) {
$data = base64_decode($edata);
$salt = substr($data, 0, 16);
$ct = substr($data, 16);
$rounds = 3; // зависит от длины ключа
$data00 = $password.$salt;
$hash = array();
$hash[0] = hash('sha256', $data00, true);
$result = $hash[0];
for ($i = 1; $i < $rounds; $i++) {
$hash[$i] = hash('sha256', $hash[$i - 1].$data00, true);
$result .= $hash[$i];
}
$key = substr($result, 0, 32);
$iv = substr($result, 32,16);
return openssl_decrypt($ct, 'AES-256-CBC', $key, true, $iv);
}
/**
* зашифровать данные алгоритмом AES 256
*
* @param data $data
* @param string $password
* @return base64 зашифрованные данные
*/
function encrypt($data, $password) {
// Установить случайную соль
$salt = openssl_random_pseudo_bytes(16);
$salted = '';
$dx = '';
// Ключ соли (32) и вектор инициализации (16) = 48
while (strlen($salted) < 48) {
$dx = hash('sha256', $dx.$password.$salt, true);
$salted .= $dx;
}
$key = substr($salted, 0, 32);
$iv = substr($salted, 32,16);
$encrypted_data = openssl_encrypt($data, 'AES-256-CBC', $key, true, $iv);
return base64_encode($salt . $encrypted_data);
}
class EncryptedSessionHandler extends SessionHandler
{
private $key;
public function __construct($key)
{
$this->key = $key;
}
public function read($id)
{
$data = parent::read($id);
if (!$data) {
return "";
} else {
return decrypt($data, $this->key);
}
}
public function write($id, $data)
{
$data = encrypt($data, $this->key);
return parent::write($id, $data);
}
}
// Здесь мы перехватываем встроенный обработчик 'files', но можно использовать любой другой
// обработчик, например 'sqlite', 'memcache' или 'memcached',
// которые предоставлены расширениями PHP.
ini_set('session.save_handler', 'files');
$key = 'secret_string';
$handler = new EncryptedSessionHandler($key);
session_set_save_handler($handler, true);
session_start();
// устанавливаем и получаем значения из $_SESSION
Замечание:
Так как методы этого класса предназначены для внутренних вызовов из PHP, как часть нормального процесса работы сессий, вызовы родительских методов из дочернего класса (иными словами "родных" обработчиков) будет возвращать
FALSE
до тех пор, пока сессия не будет запущена (автоматически или прямым вызовом session_start()). Это важный момент для понимания, особенно при тестировании, где методы класса могут быть вызваны вручную.