delfinans

Newbie | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Замещаем механизм сессий в PHP. Для замещения стандартного механизма сессий в PHP предусмотрена функция session_set_save_handler(). Базовый ее прототип выглядит так: Код: bool session_set_save_handler(string open, string close, string read, string write, string destroy, string gc) | В качестве аргументов передаются имена функций-заместителей. В случае использования ОО класса нужно передавать массивы: array('ClassName', 'method_name'). Наиболее удобным способ хранения данных сессий - использование БД. Во-первых, это защищает данные от посторонних глаз (если вы не раздаете пароль от своей базы налево и направо, конечно же). А во-вторых, это дает вам дополнительные возможности, такие как подсчет числа online пользователей или же журналирования сессий. В нашем примере для хранения данных мы будем использовать БД MySQL. Для работы нам понадобится простая таблица: Листинг 3.2.2.1, SQL: Код: CREATE TABLE sessions ( session_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, create_ts DATETIME DEFAULT 'NOW()' NOT NULL, session_key VARCHAR(255) NOT NULL, session_data TEXT NOT NULL ); | Использовать объектно-ориентированный класс смыла не много, ведь он будет всего-навсего контейнером для статических методов. Поэтому применим функционально-ориентированную методологию. Регистрационную информацию лучше указать в неком файле config.php. В нем же мы установим параметр 'session.gc_probability', который устанавливает вероятность запуска сборщика мусора (он удаляет устаревшие сессии) в процентах, а также 'session.gc_maxlifetime', который устанавливает срок годности сессий в период бездействия пользователя в секундах. На случай использования промежуточного шифрования мы также укажем ключ шифрования. Код: <?php // Сервер define('DB_HOST', 'localhost'); // Имя пользователя define('DB_USER', 'username'); // Пароль define('DB_PASS', 'password'); // Имя базы define('DB_NAME', 'test'); // Ключ для шифрования MCRYPT define('MCRYPT_CRYPT_KEY', 'my super secret key'); // Вероятность запуска сборщика мусора ini_set('session.gc_probability', 100); // Срок годности сессии при отсутствии активности пользователя ini_set('session.gc_maxlifetime', 1440); // 15 минут ?> | Теперь переходим непосредственно к написанию функций. Функция "open" открывает источник данных сессий. PHP автоматически передает ей два параметра: $save_path и $session_name. В нашем случае мы игнорируем оба аргумента, а функция sess_open() будет создавать глобальное подключение к базе данных, если таковое еще не создано. Листинг 3.2.2.3, PHP: Код: function sess_open($save_path, $session_name) { global $db; if(!is_resource($db)) $db = mysql_connect(DB_HOST, DB_USER, DB_PASS); mysql_select_db(DB_NAME, $db); return true; } | Функция "close" закрывает источник данных сессий и освобождает дополнительные ресурсы. У нас нет необходимости уничтожать какие-либо объекты или закрывать соединение с базой, поэтому мы оставляем ее почти пустой. Листинг 3.2.2.4, PHP: Код: function sess_close() { return true; } | Функция "read" должна получить данные сессии из источника в виде строки. В качестве аргумента она принимает идентификатор сессии. Если вы хотите использовать промежуточную шифрацию данных сессии, то это именно то место, где нужно вставить вызов дешифрующей функции. В нашем примере закомментирован вызов соответствующей функции библиотеки MCrypt. Листинг 3.2.2.5, PHP: Код: function sess_read($id) { global $db; $data = mysql_result(mysql_query("SELECT session_data FROM sessions WHERE session_key = '$id'")); // $data = mcrypt_ecb(MCRYPT_TripleDES, MCRYPT_CRYPT_KEY, $data, MCRYPT_DECRYPT); return $data; } | Функция записи должна создать новую сессию или же обновить данные текущей, если она существует. Ей передается идентификатор сессии и, непосредственно, данные. В случае создания новой сессии мы должны использовать INSERT запрос, а в случае обновления - UPDATE. Поэтому сначала мы проверим, существует ли сессия с таким ключем. Шифрующий вызов, как и в предыдущей функции, оставлю закомментированным. Листинг 3.2.2.6, PHP: Код: function sess_write($id, $data) { global $db; // $data = mcrypt_ecb(MCRYPT_TripleDES, MCRYPT_CRYPT_KEY, $data, MCRYPT_ENCRYPT); $num = mysql_result(mysql_query("SELECT COUNT(*) FROM sessions WHERE session_key = '$id'")); if($num == 1) { // Обновление существующей $sql = "UPDATE sessions SET session_data = '".mysql_real_escape_string($sess_data)."', create_ts = NOW() WHERE session_id = $session_id"; } else { // Создание новой $sql = "INSERT INTO sessions (create_ts, valid, session_key, session_data) VALUES (NOW(), 'yes', '". mysql_real_escape_string($id) ."', '". mysql_real_escape_string($sess_data) ."')"; } mysql_query($sql); return true; } | Для уничтожения сессии нам нужно удалить соответствующую строку таблицы. PHP передаст функции идентификатор той сессии, которую нужно удалить. Листинг 3.2.2.7, PHP: Код: function sess_destroy($id) { global $db; mysql_query("DELETE FROM sessions WHERE session_key = '$id'"); return true; } | В обязанности функции сборщика мусора входит удаление тех сессий, которыми никто не пользовался в течении установленного срока. Срок годности будет передан ей интерпретатором. Сам процесс мы осуществим всего-навсего одним SQL-запросом. Листинг 3.2.2.8, PHP: Код: function sess_gc($maxlifetime) { global $db; mysql_query("DELETE FROM sessions WHERE create_ts < DATE_ADD(now(), INTERVAL - $maxlifetime SECOND)"); return true; } | В заключение сообщаем интерпретатору, какие функции использовать для работы с сессиями. Листинг 3.2.2.9, PHP: Код: session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy', 'sess_gc') or die('Error: couldn\'t register session handler'); | Дополнительное приемущество нашего механизма заключается в том, что чтобы узнать число активных пользователей достаточно выполнить один SQL-запрос. Если вам нужны более точные данные, то нужно установить срок годности поменьше, чем стандартные 15 минут. Листинг 3.2.2.10, SQL: Код:| SELECT COUNT(*) FROM sessions | Это Форум на Исходниках.RU Системы, Сети, Технологии WWW Masters PHP, ASP, Perl, SSI, Java, Apache ... тема правда уже закрыта. Добавлено: Прошу прощения, что сразу не дал ссылку на эту страничку. Просто пришлось ее искать, она у меня сохранена. http://forum.sources.ru/index.php?showtopic=61988&st=15 Ну не знаю, может и высосана. Действительно, закрой папку с сессиями на чтение и все проблемы, но ведь хранить сессии в базе данных еще и очень удобно. Пробовал я этот вариант. Вроде бы получилось, но была одна проблема. | Всего записей: 11 | Зарегистр. 02-04-2009 | Отправлено: 23:16 07-04-2009 | Исправлено: delfinans, 23:55 07-04-2009 |
|