Насколько уникален идентификатор сеанса php

90

Насколько уникален идентификатор сеанса php? Из разных вещей, которые я читал, у меня сложилось впечатление, что я не должен полагаться на то, что два пользователя никогда не получат один и тот же идентификатор сеанса. Разве это не GUID?

Джалов
источник

Ответы:

39

Session_id действительно может быть продублирован, но вероятность очень мала. Если у вас есть веб-сайт с хорошей посещаемостью, это может случиться один раз в жизни вашего веб-сайта и просто раздражать одного пользователя за один сеанс.

Об этом не стоит беспокоиться, если вы не планируете создать веб-сайт с очень высоким трафиком или услугу для банковской отрасли.

e-satis
источник
4
Я слышал сообщения о сайтах, на которых было много случаев столкновений.
ColinM
20
Вопрос был задан почти 4 года назад. Было бы интересно узнать, импровизировал ли алгоритм идентификатора сеанса с тех пор ...
Sliq
@ColinM: и на эти сайты приходилось 1 миллион уникальных посетителей в день.
e-satis
1
По сути, это в настоящее время (хэш MD5 / SHA1) на удаленном адресе пользователя, местном времени и некотором случайном числе (LCG) .
Caramiriel
2
Мобильный ломать не нужно, мобильный постоянно ломается сам. :)
hakre
67

Он не очень уникален в том виде, в котором он был доставлен. В конфигурации по умолчанию это результат хеширования различных вещей, включая результат gettimeofday (который не очень уникален), но если вы беспокоитесь, вы должны настроить его для получения некоторой энтропии из / dev / urandom, например

ini_set("session.entropy_file", "/dev/urandom");
ini_set("session.entropy_length", "512");

ищите "php_session_create_id" в коде для фактического алгоритма, который они используют.

Отредактировано для добавления: есть генератор случайных чисел DFA, засеянный pid, смешанный со временем в usecs. Это не обязательное условие уникальности, особенно с точки зрения безопасности . Используйте конфигурацию энтропии выше.

Обновить:

Начиная с PHP 5.4.0 session.entropy_file по умолчанию имеет значение / dev / urandom или / dev / arandom, если он доступен. В PHP 5.3.0 эта директива по умолчанию оставлена ​​пустой. Руководство по PHP

djsadinoff
источник
1
Да, когда у меня был контракт на веб-сайт, который должен был быть сверхзащищенным от вражеских комбатантов и тому подобного, я фактически создал свой собственный обработчик сеанса и скармливал ему данные энтропии прямо с random.org. Но требования этой системы выходили далеко за рамки того, что имеет дело с большинством простых смертных ;-)
Теодор Р. Смит
1
@ thomas-jensen, gettimeofday - это временная метка unix, за исключением того, что она выражается в мкс (иногда). Прочтите связанный выше метод php_session_create_id.
djsadinoff
4
Изменение длины энтропии улучшает случайность, но существенно не влияет на вероятность коллизии, поскольку длина хэша остается той же. Однако изменение session.hash_function позволяет использовать более длинные хеши, например, sha512.
ColinM
2
Я считаю странным, что бывают столкновения. Конечно, PHP должен быть сделан, чтобы проверять, существует ли действительный сеанс под этим идентификатором, и впоследствии генерировать другой идентификатор ..
Люк,
1
@ theodore-r-smith, брать энтропию из общедоступного источника - действительно плохая практика. Вы должны предположить, что ваши «вражеские бойцы» также имеют доступ к random.org ...
avri
12

Если вы хотите узнать, как PHP генерирует идентификатор сеанса по умолчанию, посмотрите исходный код на Github . Это определенно не случайно и основано на хеш-коде (по умолчанию: md5) этих ингредиентов (см. Строку 310 фрагмента кода):

  1. IP-адрес клиента
  2. Текущее время
  3. PHP Linear Congruence Generator - генератор псевдослучайных чисел (PRNG)
  4. Случайный источник, зависящий от ОС - если ОС имеет доступный случайный источник (например, / dev / urandom)

Если ОС имеет доступный случайный источник, тогда сила сгенерированного идентификатора для того, чтобы быть идентификатором сеанса, высока ( / dev / urandom и другие случайные источники ОС (обычно) криптографически безопасные ГПСЧ ). Если, однако, этого не происходит, то это удовлетворительно.

Целью генерации идентификатора сеанса является:

  1. минимизировать вероятность создания двух идентификаторов сеанса с одинаковым значением
  2. сделать очень сложным с точки зрения вычислений создание случайных ключей и попадание одного из используемых .

Это достигается подходом PHP к генерации сеансов.

Вы не можете полностью гарантировать уникальность , но вероятность того, что один и тот же хэш будет дважды получена, настолько мала, что об этом, вообще говоря, не стоит беспокоиться.

GordyD
источник
11

Вы можете установить альтернативную функцию генерации хэшей, если хотите настроить способ генерации идентификатора (по умолчанию это 128-битное число, сгенерированное с помощью MD5). См. Http://www.php.net/manual/en/session.configuration.php#ini.session.hash-function

Для получения дополнительной информации о сеансах PHP, попробуйте эту отличную статью http://shiflett.org/articles/the-truth-about-sessions, которая также содержит ссылки на другие статьи о фиксации сеанса и захвате.

Пол Диксон
источник
2
Чтобы быть точным, установите "session.hash_function = sha512" для PHP 5.3 и выше, чтобы перейти к хеш-функции 512 бит. Это должно помочь. При использовании значений по умолчанию на сайтах с высокой посещаемостью часто возникают конфликты.
ColinM
5

Размер session_id
Предположим, что Seeion_id равномерно распределен и имеет размер = 128 бит. Предположим, что каждый человек на планете входит в систему один раз в день с постоянной новой сессией в течение 1000 лет.

num_sesion_ids  = 1000*365.25 *7*10**9 < 2**36
collission_prob < 1 - (1-1/2**82)**(2**36)  ≈ 1 - e**-(1/2**46) 
                ≈ 1/2**46 

Таким образом, вероятность одного или нескольких столкновений составляет менее одной из 70 тысяч миллиардов. Следовательно, 128-битный размер session_id должен быть достаточно большим. Как упоминалось в других комментариях, session_manager может также проверять, что новый session_id еще не существует.

Случайность.
Поэтому я думаю, что большой вопрос состоит в том, генерируются ли session_id: s с хорошей псевдослучайностью. В этом вы никогда не можете быть уверены, но я бы рекомендовал использовать для этой цели хорошо известное и часто используемое стандартное решение (как вы, вероятно, уже делаете).

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

MrJ
источник
3
Я не математик, но думаю, вы забываете о проблеме дня рождения, поэтому вероятность столкновения, пока она еще мала, намного выше, чем вы предполагаете. Кроме того, как предположил djsadinoff, PHP не обязательно использует хороший метод генерации случайных чисел по умолчанию.
ColinM 02
Нет, на самом деле оценка верна. Вышеприведенный расчет представляет собой упрощенную оценку, в которой мы оцениваем вероятность столкновения для session_id nr i = 1/2 82 (должно быть 1/2 92 выше, хотя = опечатка). В действительности вероятность равна (i-1) / 2 128, пока не произошло никаких предыдущих столкновений. 1/2 92 сохраняется только для последнего session_id.
MrJ 03
3

Я не нашел подтверждения по этому поводу, но я считаю, что php проверяет, существует ли уже идентификатор сеанса, прежде чем создавать его с этим идентификатором.

Проблема перехвата сеанса, о которой люди беспокоятся, - это когда кто-то узнает идентификатор сеанса активного пользователя. Этого можно избежать разными способами, для получения дополнительной информации вы можете увидеть эту страницу на php.net и этот документ по фиксации сеанса.

Олафур Вааге
источник
2
... но если вы всего лишь один php-сервер в банке из нескольких, нет никакой гарантии, что сервер обладает достаточными знаниями, чтобы знать, был ли уже использован sesssionID.
djsadinoff
Почему это имеет значение, если у меня одинаковый идентификатор сеанса на двух разных php-серверах? Предполагая, что 2 разных домена, cookie сеанса доступен только из каждого домена ...?
daremon
3
Самый простой способ предотвратить дублирование в многосерверной среде - сохранить сеансы в memcached через обработчик сеансов memcached. проблема решена, и ваши пользователи могут перемещаться по серверам различий без потери данных.
Теодор Р. Смит,
@daremon он говорит о нескольких серверах для одного домена.
gtd 02
Это просто неверно. PHP не проверяет существующие идентификаторы сеансов при создании новых. Посмотрите на любой код обработчика сеанса PHP, и для этого просто не существует метода.
ColinM 02
2

Нет, идентификатор сеанса не является GUID, но два пользователя не должны получать один и тот же идентификатор сеанса, поскольку они хранятся на стороне сервера.

штуковина
источник
2
Возможно, потому, что хранилище на стороне сервера никоим образом не гарантирует уникальность. Уникальность - это одно - при столкновении происходит столкновение независимо от того, где хранится сеанс.
Не мной, я ценю ваш ответ (как и другие). - Джалов
Джалов
2
Идентификатор сеанса хранится как на стороне сервера, так и на стороне клиента. Содержимое сеанса хранится на стороне сервера. И этот факт практически не связан с уникальностью идентификатора сессии.
YudhiWidyatama
0

Вы можете выбрать сохранение различных сеансов в БД вместе с уникальным полем создания БД; объедините два и сохраните его в переменной сеанса, затем проверьте его вместо идентификатора сеанса.

Пагубный
источник
Добро пожаловать в stackoverflow. К сожалению, ваш ответ не является попыткой ответить на вопрос. OP спросил, насколько уникальным был идентификатор сеанса. Хранение данных в базе данных с последующим использованием переменной сеанса для их извлечения только усложняет проблему, не так ли?
Ной Боэгли
@NoahBoegli другие решения предложили более сложный метод.
Пагубный
-4
<?php
session_start();
$_SESSION['username']="username";
?>

<!DOCTYPE html>
<html>
<head>
    <title>Update</title>
</head>
<body>

<table border="2">
    <tr>
        <th>Username</th>
        <th>Email</th>
        <th>Edit</th>
    </tr>
<?php
     $conn=mysqli_connect("localhost","root","","telephasic");
     $q2="select * from register where username = '".$_SESSION['username']."'";
     $run=mysqli_query($conn, $q2);
     while($row=mysqli_fetch_array($run))
     {
         $name=$row[1];
         $email=$row[2];
     ?>

    <tr>
        <td><?php echo $name; ?></td>
        <td><?php echo $email; ?></td>
        <td><a href="edit.php"> Edit </a></td>
    </tr>
 <?php } ?>
 </table> 
 </body>

если ваше имя пользователя отличается или уникально, вы можете использовать этот код для сеанса

Арун Шарма
источник