php会话ID有多独特


90

php会话ID有多独特?我从阅读过的各种东西中得到的印象是,我不应该依赖永远不会获得相同sessionid的两个用户。它不是GUID吗?

Answers:


39

Session_id确实可以复制,但是概率很低。如果您的网站访问量比较合理,则可能会在您的网站生命中发生一次,并且只会使一个会话的用户烦恼。

除非您期望为银行业建立一个流量很高的网站或服务,否则这是不值得关注的。


4
我听说过许多发生冲突的网站的报道。
ColinM

20
这个问题已在近4年前提出。知道会话ID算法自那时以来是否即
兴起

@ColinM:这些站点每天有100万唯一身份访问者。
e-satis 2012年

1
相应地,其当前基于用户的远程地址,本地时间和某个随机数(LCG)(MD5 / SHA1哈希
Caramiriel

2
我不需要打破移动性,移动不断地自我突破。:)
hakre 2014年

67

它并不是很独特。在默认配置中,它是各种事物的散列的结果,包括gettimeofday的结果(这并不是唯一的),但是如果您担心的话,应该配置它以从/ dev / urandom提取一些熵,就像这样

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

代码中搜索“ php_session_create_id”,了解他们使用的实际算法。

编辑添加:pid播有一个DFA随机数生成器,与usecs中的时间混合在一起。从安全角度来看,这不是一个牢固的唯一性条件。使用上面的熵配置。

更新:

从PHP 5.4.0开始,session.entropy_file默认为/ dev / urandom或/ dev / arandom(如果可用)。在PHP 5.3.0中,该指令默认为空。PHP手册


1
是的,当我是一个网站的合同时,该网站必须对敌方战斗人员具有极高的安全性,实际上,我创建了自己的会话处理程序,并直接从random.org提供了熵数据。但是该系统的要求远远超出了大多数凡人所能达成的标准;
西奥多·R·史密斯

1
@ thomas-jensen,gettimeofday unix时间戳,除了它以μsec(有时)表示。阅读上面链接的php_session_create_id方法。
djsadinoff 2011年

4
更改熵的长度可以改善随机性,但不会显着影响冲突的可能性,因为哈希值仍是相同的长度。但是,更改session.hash_function允许您使用更长的哈希,例如sha512。
ColinM

2
我觉得有冲突很奇怪。当然PHP提出,要检查是否有该ID在一个有效的会话,并随后产生不同的ID ..
卢克

1
@ theodore-r-smith,从公开来源获取熵确实是一个坏习惯。您应该假设您的“敌方战斗人员”也可以访问random.org ...
2015年

12

如果您想了解PHP默认情况下如何生成会话ID,请查看Github上的源代码。它肯定不是随机的,并且基于这些成分的哈希值(默认值:md5)(请参见代码段的310行):

  1. 客户端的IP地址
  2. 当前时间
  3. PHP线性同余生成器 -伪随机数生成器(PRNG)
  4. 特定于操作系统的随机源 -如果操作系统具有可用的随机源(例如/ dev / urandom)

如果OS具有可用的随机源,则出于成为会话ID的目的,生成的ID的强度很高(/ dev / urandom和其他OS随机源(通常)是密码安全的PRNG)。如果不是这样,那就令人满意了。

会话标识生成的目标是:

  1. 最小化生成具有相同值的两个会话ID的可能性
  2. 生成随机密钥并击中使用中的密钥使计算变得非常困难

这是通过PHP的会话生成方法来实现的。

您不能绝对保证唯一性,但是两次击中相同哈希的概率很低,通常来说,这是不值得担心的。


11

如果要自定义ID的生成方式,则可以安装其他哈希生成功能(默认情况下,它是通过MD5生成的128位数字)。参见http://www.php.net/manual/en/session.configuration.php#ini.session.hash-function

有关PHP会话的更多信息,请尝试这篇出色的文章http://shiflett.org/articles/the-truth-about-sessions,该文章还链接到其他有关会话固定和劫持的文章。


2
确切地说,为PHP 5.3设置“ session.hash_function = sha512”,最高可达512位哈希。这应该可以解决问题。使用默认设置时,在交通繁忙的站点上经常会发生碰撞。
ColinM

5

session_id的大小
假定seesion_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 

因此,一次或多次碰撞的可能性小于7万亿次。因此,session_id的128位大小应该足够大。如其他注释中所述,session_manager可能还会检查新的session_id不存在。

随机性
因此,我认为最大的问题是session_id:s是否以良好的伪随机性生成。关于这一点,您永远不能确定,但​​是我建议为此目的使用一种众所周知且经常使用的标准解决方案(就像您可能已经做过的那样)。

即使通过检查避免了冲突,session_id的随机性和大小也很重要,因此黑客无法以某种方式进行合格的猜测并以很高的概率找到活动的session_id:s。


3
我不是数学家,但我认为您忘记了生日问题,因此碰撞的机会虽然很小,但比您建议的要大得多。另外,正如djsadinoff所建议的那样,PHP不一定会使用默认情况下生成随机数的良好方法。
ColinM

估计实际上没有成立。上面的计算是一个简化的估计,其中我们估计session_id nr i发生碰撞的概率为= 1/2 82(尽管应该是 = typo,但应该是1/2 92)。实际上,只要以前没有发生碰撞,则概率为(i-1)/ 2 128。1/2 92仅适用于最后一个session_id。
MrJ 2012年

3

我尚未对此进行确认,但是我相信php在创建具有该ID的会话ID之前会检查其是否已存在。

人们担心的会话劫持问题是当有人发现活动用户的会话ID时。可以通过多种方式防止这种情况发生,有关更多信息,您可以在php.net上查看此页面,以及有关会话固定的本文


2
...但是,如果您只是一小群中的一台php服务器,则无法保证该服务器具有足够的知识来知道sesssionID是否已被使用。
djsadinoff

如果在2个不同的php服务器中获得相同的会话ID,为什么会很重要?假设有2个不同的域,则只能从每个域访问会话cookie ...?
daremon

3
在多服务器环境中防止重复的最简单方法是通过memcached会话处理程序将会话存储在memcached中。问题解决了,您的用户可以绕过差异服务器而不会丢失自己的东西。
西奥多·R·史密斯

@daremon他正在谈论一个域的多个服务器。
gtd

这根本是不正确的。在生成新会话ID时,PHP不会检查现有会话ID。查看任何PHP会话处理程序代码,根本没有实现此目的的方法。
ColinM

2

不,会话ID不是GUID,但是两个用户不应获得与存储在服务器端相同的会话ID。


2
可能是因为服务器端存储无法以任何方式保证唯一性。唯一性是一件事-如果发生冲突,无论会话存储在何处,冲突都会发生冲突。

不是我本人,我感谢您(以及其他人)的回应。-Jalov
Jalov

2
会话ID既存储在服务器端,又存储在客户端。会话内容存储在服务器端。而且事实几乎与会话ID的唯一性无关。
YudhiWidyatama

-3
<?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>

如果您的用户名不同或唯一,则可以使用此代码进行会话

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.