Хранение PHP сесcий в базе данных
Сегодня я Вам поведаю как хранить сесcии для PHP в базе данных. По умолчанию PHP использует для хранения сессий дисковые файлы(одна сессия в один файл, где название файла – session_id). Файл создается, как только новая сессия начинает, и удаляется, когда сессия заканчивается (или истекает). Это совершенно нормально для большинства обстоятельств, но имеет следующие недостатки:
- Если Вы используете разделенный сервер тогда, другие пользователи того сервера могут быть в состоянии получить доступ к вашим файлам сессии, таким образом ставя под угрозу безопасность вашего сайта.
- Каждый сервер будет иметь собственную директорию для хранения сесcий и, если Вы используете балансировшик нагрузок, то нет никакой гарантии, что следующий запрос придет на тот сервер, где была создана сесия.
- Было бы трудно для администратора выполнить следующие вопросы: «сколько сессий в настоящее время активно?», «какие пользователи в настоящее время логинятся?»
1. Создание таблицы
Сначала давайте создадим таблицу для хранения сеcсий. Для mysql
-
CREATE TABLE `php_session` (
-
`session_id` varchar(32) NOT NULL DEFAULT »,
-
`date_created` datetime NOT NULL DEFAULT ’0000-00-00 00:00:00′,
-
`last_updated` datetime NOT NULL DEFAULT ’0000-00-00 00:00:00′,
-
`session_data` longtext,
-
PRIMARY KEY (`session_id`),
-
KEY `last_updated` (`last_updated`)
-
) ENGINE=MyISAM
или для postgresql
-
CREATE TABLE php_session (
-
session_id character varying(32) DEFAULT »::character varying NOT NULL,
-
date_created timestamp WITH time zone NOT NULL,
-
last_updated timestamp WITH time zone NOT NULL,
-
session_data text
-
);
-
-
ALTER TABLE ONLY php_session
-
ADD CONSTRAINT php_session_pkey PRIMARY KEY (session_id);
Поля
| session_id | Идентификатор для сесии, первичный ключ. |
| session_data | Поле должно быть достаточно большим что б сохранить $_SESSION данные |
| date_created | Используется что б узнать когда стартовала сесия. |
| last_updated | Используется, что б узнать когда был последний запрос от пользователя. Также это поле будет использоваться для чистки сесии. |
2. Создание класа PHP_Session
Создадим класс для работы с сесcиями. Начнем с конструктора
-
<?php
-
class php_Session extends Default_Table
-
{
-
// ****************************************************************************
-
// class constructor
-
// ****************************************************************************
-
function __construct ()
-
{
-
// save directory name of current script
-
-
$this->dbname = ‘audit’;
-
$this->tablename = ‘php_session’;
-
-
} // php_Session
Коротко говоря в конструкторе я инициализирую подключение к базе данных и таблице php_session
Дальше добавим метод open()
-
function open ($save_path, $session_name)
-
// open the session.
-
{
-
// do nothing
-
return TRUE;
-
-
} // open
В нем мы ничего не делаем
-
function close ()
-
// close the session.
-
{
-
// perform garbage collection
-
return $result;
-
} // if
-
-
return FALSE;
-
-
} // close
Метод close() вызывается, когда сесcия закрывается, в данном случае просто запускаем чистильшика сесий (метод gc).
-
function read ($session_id)
-
// read any data for this session.
-
{
-
-
$this->fieldarray = $fieldarray[0];
-
$this->fieldarray[‘session_data’] = »;
-
return $fieldarray[0][‘session_data’];
-
} else {
-
return »; // return an empty string
-
} // if
-
-
} // read
Метод используется для чтения данных из сесcии. В нашем случае выбираем поле по $session_id из таблицы и возращаем все, что есть в session_data.
-
function write ($session_id, $session_data)
-
// write session data to the database.
-
{
-
if ($this->fieldarray[‘session_id’] != $session_id) {
-
// user is starting a new session with previous data
-
} // if
-
} // if
-
-
// create new record
-
$array[‘session_id’] = $session_id;
-
$array[‘date_created’] = getTimeStamp();
-
$array[‘last_updated’] = getTimeStamp();
-
$this->_dml_insertRecord($array);
-
} else {
-
// update existing record
-
$array[‘last_updated’] = getTimeStamp();
-
$this->_dml_updateRecord($array, $this->fieldarray);
-
} // if
-
-
return TRUE;
-
-
} // write
Метод write() обновляет или же (если ещё данных в сеcсию не поступало) создает ячейку данных в таблице для данных в сесии по $session_id.
-
function destroy ($session_id)
-
// destroy the specified session.
-
{
-
$fieldarray[‘session_id’] = $session_id;
-
$this->_dml_deleteRecord($fieldarray);
-
-
return TRUE;
-
-
} // destroy
Метод destroy() используется для уничтожения сеcсии (в нашем случае удаляем ячейку в таблице по $session_id).
-
function __destruct ()
-
// ensure session data is written out before classes are destroyed
-
// (see http://bugs.php.net/bug.php?id=33772 for details)
-
{
-
-
} // __destruct
На всяк случай деструктор (по ссылочке со старым PHP данный метод не будет работать без этого).
-
function gc ($max_lifetime)
-
// perform garbage collection.
-
{
-
-
$count = $this->_dml_deleteSelection("last_updated < ‘$dt2‘");
-
-
return TRUE;
-
-
} // gc
Метод gc используется для чистки сесий (у которых время жизни прошло). Параметр $max_lifetime указывает сколько может существовать сесия (в секундах). В нашем случае мы удаляем запросом по last_updated < текушее время – $max_lifetime сесии, у которых TTL уже прошло.
Все, наш класс готов. Теперь можем его попытаться использовать
-
require_once ‘classes/php_session.class.php’;
-
$session_class = new php_Session;
Вот, теперь можем дальше оперировать с сесиями как не в чем не бывало. Но теперь в таблице появятся приблизительно такие строчки
Вот и все.
В заключение
Вы увидели, что это – относительно простой процесс, чтобы переключить регистрацию данных сессии от обычных дисковых файлов до базы данных. Это преодолевает недостатки, созданые с обычными дисковыми файлами:
- Данные сессии более безопасны, поскольку потенциальный хакер должен быть подключен к базе данных прежде, чем он может получить доступ к чему – нибудь.
- Использование многократных серверов не создает для нас проблему, поскольку все данные сессии теперь хранятся в единственном центральном месте и доступны всем серверам.
- Намного легче выбрать из базы данных информацию о текущих сессиях или текущих пользователях.
А где учет того факта, что id-сессии может меняться в течение работы?
И как вы себе это представляете?
Хотелось бы что-то наваять в комментах креативного, но мысль не складывается, так что просто “зачОт”
class php_Session extends Default_Table
Выложите Default_Table если не сложно
Default_Table – это класс для работы с базой данных, основные методы
_dml_getData – берет данные
_dml_insertRecord – вставляет данные в таблицу
_dml_deleteSelection – удаляет из таблицы данные
Это все, что вам надо.
ЗЫ
Выковырять будет его тяжеловато, я его привязывал к одному проекту.