PHP 8.4.1 Released!

session_create_id

(PHP 7 >= 7.1.0, PHP 8)

session_create_idСоздаёт новый идентификатор сессии

Описание

session_create_id(string $prefix = ""): string|false

Функция session_create_id() создаёт новый идентификатор текущей сессии. Функция возвращает идентификатор сессии без коллизий.

При неактивной сессии проверка на коллизии опускается.

Функция создаёт идентификатор сессии, который соответствует настройкам файла конфигурации php.ini.

Скрипт, который содержит задание по сборке мусора, требуется запускать с тем же идентификатором пользователя, от имени которого запускается процесс веб-сервера. Несовпадение идентификаторов вызывает проблемы с разрешениями, которые острее остальных проявляются при работе дескриптора сохранения файлов.

Список параметров

prefix

Функция добавит префикс prefix в начало нового идентификатора сессии, если параметр prefix указали. Не каждый символ разрешается указывать в идентификаторе сессии. В идентификаторе сессии допускаются только символы из диапазона: [a-zA-Z0-9,-]. Максимальная длина идентификатора — 256 символов.

Возвращаемые значения

Функция session_create_id() возвращает новый идентификатор текущей сессии без коллизий. Функция не проверяет идентификатор на коллизии при неактивной сессии. Функция возвращает false, если возникла ошибка.

Примеры

Пример #1 Пример использования функции session_create_id() с функцией session_regenerate_id()

<?php

// Функция запуска сессии с поддержкой управления сессиями на основе временны́х меток
function my_session_start()
{
session_start();

// Не разрешать слишком старый идентификатор сессии
if (!empty($_SESSION['deleted_time']) && $_SESSION['deleted_time'] < time() - 180) {
session_destroy();
session_start();
}
}

// Функция обновления идентификатора сессии
function my_session_regenerate_id()
{
// Вызываем функцию session_create_id(), пока сессия активна, чтобы гарантировать,
// что не возникнет коллизий
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
// ВНИМАНИЕ: Никогда не указывайте как префикс конфиденциальные строки!
$newid = session_create_id('myprefix-');

// Устанавливаем временну́ю метку удаления данных текущей сессии.
// По ряду причин данные активной сессии не нужно удалять сразу
$_SESSION['deleted_time'] = time();

// Записываем данные сессии и завершаем её
session_write_close();

// Убедимся, что PHP принимает пользовательский идентификатор сессии
// ЗАМЕЧАНИЕ: Разработчики PHP рекомендуют включать опцию use_strict_mode, чтобы защитить приложение от уязвимостей
ini_set('session.use_strict_mode', 0);

// Устанавливаем новый пользовательский идентификатор сессии
session_id($newid);

// Запускаем сессию с пользовательским идентификатором
session_start();
}

// Убеждаемся, что включили строгий режим сессий, который устанавливает опция use_strict_mode.
// Опция use_strict_mode обязательна по соображениям безопасности
ini_set('session.use_strict_mode', 1);
my_session_start();

// Идентификатор сессии требуется генерировать, когда:
// - Пользователь вошёл в систему
// - Пользователь вышел из системы
// - По прошествии конкретного периода времени
my_session_regenerate_id();

// С этого места пишем полезный код программы

?>

Смотрите также

Добавить

Примечания пользователей 1 note

up
4
rowan dot collins at gmail dot com
6 years ago
This function is very hard to replicate precisely in userland code, because if a session is already started, it will attempt to detect collisions using the new "validate_sid" session handler callback, which did not exist in earlier PHP versions.

If the handler you are using implements the "create_sid" callback, collisions may be detected there. This is called when you use session_regenerate_id(), so you could use that to create a new session, note its ID, then switch back to the old session ID. If no session is started, or the current handler doesn't implement "create_sid" and "validate_sid", neither this function nor session_regenerate_id() will guarantee collision resistance anyway.

If you have a suitable definition of random_bytes (a library is available to provide this for versions right back to PHP 5.3), you can use the following to generate a session ID in the same format PHP 7.1 would use. $bits_per_character should be 4, 5, or 6, corresponding to the values of the session.hash_bits_per_character / session.sid_bits_per_character ini setting. You will then need to detect collisions manually, e.g. by opening the session and confirming that $_SESSION is empty.

<?php
function session_create_random_id($desired_output_length, $bits_per_character)
{
$bytes_needed = ceil($desired_output_length * $bits_per_character / 8);
$random_input_bytes = random_bytes($bytes_needed);

// The below is translated from function bin_to_readable in the PHP source (ext/session/session.c)
static $hexconvtab = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,-';

$out = '';

$p = 0;
$q = strlen($random_input_bytes);
$w = 0;
$have = 0;

$mask = (1 << $bits_per_character) - 1;

$chars_remaining = $desired_output_length;
while (
$chars_remaining--) {
if (
$have < $bits_per_character) {
if (
$p < $q) {
$byte = ord( $random_input_bytes[$p++] );
$w |= ($byte << $have);
$have += 8;
} else {
// Should never happen. Input must be large enough.
break;
}
}

// consume $bits_per_character bits
$out .= $hexconvtab[$w & $mask];
$w >>= $bits_per_character;
$have -= $bits_per_character;
}

return
$out;
}
?>
To Top