【发布时间】:2010-09-13 09:53:45
【问题描述】:
php 会话 ID 的唯一性如何?我从读过的各种内容中得到的印象是,我不应该依赖两个用户永远不会获得相同的 sessionid。不是 GUID 吗?
【问题讨论】:
php 会话 ID 的唯一性如何?我从读过的各种内容中得到的印象是,我不应该依赖两个用户永远不会获得相同的 sessionid。不是 GUID 吗?
【问题讨论】:
不,会话 ID 不是 GUID,但两个用户不应获得相同的会话 ID,因为它们存储在服务器端。
【讨论】:
我还没有找到对此的确认,但我相信 php 在创建具有该 ID 的会话 ID 之前会检查会话 ID 是否已经存在。
人们担心的会话劫持问题是当有人发现活跃用户的会话 ID 时。这可以通过多种方式防止,有关更多信息,您可以在 php.net 上查看 this page 和 this paper on session fixation
【讨论】:
如果您想自定义生成 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,该文章还链接到有关会话固定和劫持的其他文章。
【讨论】:
它在发货时并不是很独特。在默认配置中,它是各种事物的哈希结果,包括 gettimeofday 的结果(这并不是非常独特),但如果您担心,您应该将其配置为从 /dev/urandom 中提取一些熵,就像这样
ini_set("session.entropy_file", "/dev/urandom");
ini_set("session.entropy_length", "512");
在the code 中搜索“php_session_create_id”以了解他们正在使用的实际算法。
编辑添加: 有一个由 pid 播种的 DFA 随机数生成器,与 usecs 中的时间混合。这不是一个确定的唯一性条件especially from a security perspective。使用上面的熵配置。
更新:
从 PHP 5.4.0 开始 session.entropy_file 默认为 /dev/urandom 或 /dev/arandom 如果可用。在 PHP 5.3.0 中保留了该指令 默认为空。 PHP Manual
【讨论】:
Session_id确实可以重复,但是概率很低。如果您有一个流量公平的网站,它可能会在您的网站生命中发生一次,并且只会在一次会话中惹恼一位用户。
这不值得关心,除非你期望为银行业建立一个非常高流量的网站或服务。
【讨论】:
session_id 的大小
假设 seesion_id 是均匀分布的,并且 size=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 亿分之一。因此 128 位的 session_id 应该足够大。正如在其他 cmets 中提到的,session_manager 也可能会检查新的 session_id 是否已经存在。
随机性
因此,我认为最大的问题是 session_id:s 是否以良好的伪随机性生成。关于这一点,您永远无法确定,但我建议为此目的使用众所周知且经常使用的标准解决方案(您可能已经这样做了)。
即使通过检查避免了冲突,session_id的随机性和大小也很重要,这样黑客就无法以某种方式进行有条件的猜测并以很大的概率找到活跃的session_id。
【讨论】:
如果您想了解 PHP 默认如何生成会话 ID,请查看 Github 上的源代码。它当然不是随机的,而是基于这些成分的散列(默认值:md5)(参见代码 sn-p 的第 310 行):
如果操作系统有可用的随机源,则生成的 ID 作为会话 ID 的强度很高(/dev/urandom 和其他操作系统随机源(通常)是加密安全的 PRNG)。但是,如果它没有,那么它是令人满意的。
生成会话标识的目标是:
这是通过 PHP 的会话生成方法实现的。
你不能绝对保证唯一性,但是两次命中同一个哈希的概率是如此之低,一般来说,不值得担心。
【讨论】:
<?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>
如果您的用户名不同或唯一,您可以使用此代码进行会话
【讨论】:
您可以选择将各种会话与数据库生成唯一字段一起存储在数据库中;将两者合并并将其保存在会话变量中,然后检查该变量而不是会话 ID。
【讨论】:
我知道这篇文章很老了。然而,我在这里添加我的答案,因为我找不到这个问题的相关解决方案,即使在我自己发布了一个类似的问题之后。然而,我从对我的帖子的回复中得到了线索。对于那些对算法和解决方案感兴趣的人,here 进行了解释。它使用会话和不同 cookie 的组合。
简单的算法是这样的
会话处理将通过使用 DB 的自定义类“MySessionHandler”完成
1.就在 session_start 之前,cookie cookie_start_time 被设置为当前时间。此 cookie 的生命周期将与会话的生命周期相同。两者都使用变量 $this->cookieLifeTime 来设置生命周期。
在会话“_write”中,我们将该值设置为 db 表字段 cookie_start_time 与 $this->cookieStartTime 相同
在会话“_read”中我们进行检查
if($getRowsOfSession[0]['cookie_start_time'] != $this->cookieStartTime).
如果返回 true,则表示这是一个重复会话,用户被重定向以销毁会话并再次重定向以启动新会话。(总共 2 次重定向)
【讨论】: