92

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

4

10 回答 10

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 手册

于 2008-09-26T11:01:35.797 回答
41

session_id确实可以重复,但是概率很低。如果您有一个流量公平的网站,它可能会在您的网站生活中发生一次,并且只会在一次会话中惹恼一位用户。

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

于 2008-09-26T11:25:54.770 回答
12

如果您想知道 PHP 默认如何生成会话 ID,请查看Github上的源代码。它当然不是随机的,而是基于这些成分的散列(默认值:md5)(参见代码片段的第 310 行):

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

如果操作系统有可用的随机源,则生成的 ID 的强度作为会话 ID 的强度很高(/dev/urandom 和其他操作系统随机源(通常)是加密安全的 PRNG)。但是,如果它没有,那么它是令人满意的。

会话标识生成的目标是:

  1. 最小化生成两个具有相同值的会话 ID 的概率
  2. 使生成随机密钥并命中一个正在使用的密钥在计算上变得非常具有挑战性

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

你不能绝对保证唯一性,但是两次命中相同哈希的概率是如此之低,一般来说,不值得担心。

于 2014-12-04T15:45:59.937 回答
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,它还链接到有关会话固定和劫持的其他文章。

于 2008-09-26T11:01:28.620 回答
6

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 

所以发生一次或多次碰撞的概率小于七亿分之一。因此 session_id 的 128 位大小应该足够大。正如其他评论中提到的, session_manager 也可能会检查新的 session_id 是否不存在。

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

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

于 2012-06-13T22:42:42.087 回答
3

我还没有找到对此的确认,但我相信 php 在创建具有该 ID 的会话 ID 之前会检查会话 ID 是否已经存在。

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

于 2008-09-26T10:53:13.603 回答
2

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

于 2008-09-26T10:50:50.143 回答
0

您可以选择将各种会话与数据库生成唯一字段一起存储在数据库中;合并两者并将其保存在会话变量中,然后检查那个而不是会话ID。

于 2020-09-23T10:22:22.687 回答
0

我知道这篇文章很老了。然而,我在这里添加我的答案,因为我找不到这个问题的相关解决方案,即使在我自己发布了一个类似的问题之后。然而,我从对我的帖子的回复中得到了线索。对于那些感兴趣的人,这里解释了算法和解决方案。它使用会话和不同 cookie 的组合。

算法简而言之是这样的

会话处理将通过使用 DB 的自定义类“MySessionHandler”完成

1.就在 session_start 之前,一个 cookie cookie_start_time 被设置为当前时间。此 cookie 的生命周期将与会话的生命周期相同。两者都使用变量 $this->cookieLifeTime 来设置生命周期。

  1. 在会话“_write”中,我们将该值设置为 db 表字段 cookie_start_time 与 $this->cookieStartTime 相同

  2. 在会话“_read”中,我们进行检查

if($getRowsOfSession[0]['cookie_start_time'] != $this->cookieStartTime)。

如果它返回 true,则意味着这是一个重复会话,并且用户被重定向以销毁会话并再次重定向以启动新会话。(总共 2 次重定向)

于 2021-05-13T05:06:17.913 回答
-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>

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

于 2018-07-23T08:48:23.503 回答