簡體   English   中英

php 會話 id 的唯一性

[英]How unique is the php session id

php 會話 ID 有多獨特? 我從我讀過的各種事情中得到的印象是,我不應該依賴兩個永遠不會獲得相同 sessionid 的用戶。 不是GUID嗎?

它在發貨時並不是很獨特。 在默認配置中,它是各種事物的散列結果,包括 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手冊

Session_id 確實可以復制,但是概率很低。 如果您有一個流量公平的網站,它可能會在您的網站生活中發生一次,並且只會在一次會話中惹惱一個用戶。

除非您希望為銀行業建立一個非常高流量的網站或服務,否則這不值得關心。

如果您想知道 PHP 如何默認生成會話 ID,請查看Github上的源代碼。 它當然不是隨機的,並且基於這些成分的散列(默認值:md5)(參見代碼片段的第 310 行):

  1. 客戶端的IP地址
  2. 當前時間
  3. PHP Linear Congruence Generator - 一個偽隨機數生成器 (PRNG)
  4. 操作系統特定的隨機源- 如果操作系統有可用的隨機源(例如 /dev/urandom)

如果操作系統有一個可用的隨機源,那么為了成為會話 ID 的目的而生成的 ID 的強度很高( /dev/urandom 和其他操作系統隨機源(通常)是加密安全的 PRNGs )。 然而,如果它沒有,那么它是令人滿意的。

會話標識生成的目標是:

  1. 最小化生成具有相同值的兩個會話 ID 的概率
  2. 使生成隨機密鑰並命中使用中的密鑰在計算上變得非常具有挑戰性

這是通過 PHP 的會話生成方法實現的。

你不能絕對保證唯一性,但是兩次命中相同哈希的概率很低,一般來說,不值得擔心。

如果您想自定義 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 ,其中還鏈接到有關會話固定和劫持的其他文章。

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。

我還沒有找到對此的確認,但我相信 php 在創建具有該 ID 的會話 ID 之前會檢查該會話 ID 是否已經存在。

人們擔心的會話劫持問題是當有人發現活動用戶的會話 ID 時。 這可以通過多種方式防止,有關更多信息,您可以在 php.net 上查看此頁面有關會話固定的這篇論文

不,會話 ID 不是 GUID,但兩個用戶不應獲得相同的會話 ID,因為它們存儲在服務器端。

您可以選擇將各種會話存儲在 DB 上以及 DB 生成唯一字段; 合並兩者並將其保存在會話變量中,然后檢查那個而不是會話 ID。

我知道這個帖子很老了。 然而,我在這里添加我的答案,因為我找不到這個問題的相關解決方案,即使在我自己發布了一個類似的問題之后。 然而,我從對我的帖子的回復中得到了一個線索。 對於那些對算法和解決方案感興趣的人, 這里解釋 它使用會話和不同 cookie 的組合。

簡要的算法是這樣的

會話處理將使用 DB 使用自定義類“MySessionHandler”完成

1.就在 session_start 之前,cookie cookie_start_time 設置為當前時間。 此 cookie 的生命周期將與會話的生命周期相同。 兩者都使用變量 $this->cookieLifeTime 來設置生命周期。

  1. 在會話“_write”中,我們將該值設置為與 $this->cookieStartTime 相同的數據庫表字段 cookie_start_time

  2. 在會話“_read”中,我們進行了檢查

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

如果返回 true,則表示這是一個重復的會話,用戶被重定向以銷毀會話並再次重定向以啟動新會話。(總共 2 次重定向)

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

如果您的用戶名不同或唯一,您可以使用此代碼進行會話

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM