session_create_id

(PHP 7 >= 7.1.0, PHP 8)

session_create_id β€” Π‘ΠΎΠ·Π΄Π°Ρ‘Ρ‚ Π½ΠΎΠ²Ρ‹ΠΉ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ сСссии

ОписаниС

function 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();

// Π‘ этого мСста пишСм ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

?>

Π‘ΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅

  • session_regenerate_id() - Π“Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈ обновляСт ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ сСссии
  • session_start() - НачинаСт ΠΈΠ»ΠΈ возобновляСт сСссию
  • session.use_strict_mode
  • SessionHandler::create_sid() - Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠ²Ρ‹ΠΉ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ сСссии
οΌ‹Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΡ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ 1 note

up
3
rowan dot collins at gmail dot com ΒΆ
8 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;
}
?>