session_regenerate_id

(PHP 4 >= 4.3.2, PHP 5, PHP 7, PHP 8)

session_regenerate_id 使用新生成的會(huì)話 ID 更新現(xiàn)有會(huì)話 ID

說明

session_regenerate_id(bool $delete_old_session = false): bool

session_regenerate_id() 在不修改當(dāng)前會(huì)話中數(shù)據(jù)的前提下使用新的 ID 替換原有會(huì)話 ID。

如果啟用了 session.use_trans_sid 選項(xiàng), 那么必須在調(diào)用 session_regenerate_id() 函數(shù)之后開始進(jìn)行輸出工作, 否則會(huì)導(dǎo)致使用原有的會(huì)話 ID。

警告

當(dāng)前的 session_regenerate_id 并沒有很好的處理在諸如移動(dòng)數(shù)據(jù)網(wǎng)絡(luò)和 WiFi 網(wǎng)絡(luò)不穩(wěn)定的場景。 因此,調(diào)用 session_regenerate_id 函數(shù) 可能會(huì)導(dǎo)致會(huì)話丟失。

你不應(yīng)該直接銷毀舊的會(huì)話所關(guān)聯(lián)的數(shù)據(jù), 而是應(yīng)該使用時(shí)間戳機(jī)制來控制對于已經(jīng)失效的會(huì)話 ID 的訪問。 否則,可能會(huì)在并發(fā)訪問的場景下導(dǎo)致會(huì)話數(shù)據(jù)不一致、 會(huì)話丟失等情況,甚至可能引發(fā)客戶端(瀏覽器)創(chuàng)建很多無用的會(huì)話 ID。 但是,另外一方面來講,立即刪除會(huì)話中的數(shù)據(jù) 可以防止會(huì)話劫持攻擊。

參數(shù)

delete_old_session

是否刪除原 ID 所關(guān)聯(lián)的會(huì)話存儲(chǔ)文件。 如果你需要避免會(huì)話并發(fā)訪問沖突,那么不應(yīng)該立即刪除會(huì)話中的數(shù)據(jù)。 如果你需要防止會(huì)話劫持攻擊,那么可以立即刪除會(huì)話數(shù)據(jù)。

返回值

成功時(shí)返回 true, 或者在失敗時(shí)返回 false。

范例

示例 #1 A session_regenerate_id() 示例

<?php
// 注意:下列不是完整的代碼,只是一個(gè)示例

session_start();

// 檢查會(huì)話被銷毀的時(shí)間戳
if (isset($_SESSION['destroyed'])
    && 
$_SESSION['destroyed'] < time() - 300) {
    
// 通常不會(huì)發(fā)生這種情況。如果發(fā)生,那么可能是由于不穩(wěn)定的網(wǎng)絡(luò)狀況或者被攻擊導(dǎo)致的
    // 移除用戶會(huì)話中的認(rèn)證信息
    
remove_all_authentication_flag_from_active_sessions($_SESSION['userid']);
    throw(new 
DestroyedSessionAccessException);
}

$old_sessionid session_id();

// 設(shè)置會(huì)話銷毀時(shí)間戳
$_SESSION['destroyed'] = time(); // 從 PHP 7.0.0 開始, session_regenerate_id() 會(huì)自動(dòng)保存會(huì)話數(shù)據(jù)

// 如果直接調(diào)用 session_regenerate_id() 函數(shù)可能會(huì)導(dǎo)致會(huì)話丟失的情況,
// 參見下面的例程
session_regenerate_id();

// 新創(chuàng)建的會(huì)話不需要時(shí)間戳
unset($_SESSION['destroyed']);

$new_sessionid session_id();

echo 
"Old Session: $old_sessionid<br />";
echo 
"New Session: $new_sessionid<br />";

print_r($_SESSION);
?>

當(dāng)前的會(huì)話模塊未能很好的處理在網(wǎng)絡(luò)不穩(wěn)定的時(shí)候?qū)е聲?huì)話丟失的場景。 你需要自行管理會(huì)話 ID 避免調(diào)用 session_regenerate_id 導(dǎo)致會(huì)話丟失。

示例 #2 Avoiding lost session by session_regenerate_id()

<?php
// 注意:下列不是完整的代碼,只是一個(gè)示例
// my_session_start() 和 my_session_regenerate_id()
// 函數(shù)可以避免在網(wǎng)絡(luò)不穩(wěn)定的情況下導(dǎo)致會(huì)話丟失的問題。
// 并且還可以避免用戶會(huì)話被攻擊者利用

function my_session_start() {
    
session_start();
    if (isset(
$_SESSION['destroyed'])) {
       if (
$_SESSION['destroyed'] < time()-300) {
           
// 通常不會(huì)發(fā)生這種情況。如果發(fā)生,那么可能是由于不穩(wěn)定的網(wǎng)絡(luò)狀況或者被攻擊導(dǎo)致的
           // 移除用戶會(huì)話中的認(rèn)證信息
           
remove_all_authentication_flag_from_active_sessions($_SESSION['userid']);
           throw(new 
DestroyedSessionAccessException);
       }
       if (isset(
$_SESSION['new_session_id'])) {
           
// 尚未完全過期,可能是由于網(wǎng)絡(luò)不穩(wěn)定引起的。
           // 嘗試再次設(shè)置正確的會(huì)話 ID cookie。
           // 注意:如果你需要移除認(rèn)證標(biāo)記,那么不要嘗試再次設(shè)置會(huì)話 ID。
           
session_commit();
           
session_id($_SESSION['new_session_id']);
           
// 現(xiàn)在有了新的會(huì)話 ID 了。
           
session_start();
           return;
       }
   }
}

function 
my_session_regenerate_id() {
    
// 如果由于不穩(wěn)定的網(wǎng)絡(luò)導(dǎo)致沒有創(chuàng)建會(huì)話 ID,
    // 那么就創(chuàng)建一個(gè)
    
$new_session_id session_create_id();
    
$_SESSION['new_session_id'] = $new_session_id;
    
    
// 設(shè)置銷毀時(shí)間戳
    
$_SESSION['destroyed'] = time();
    
    
// 保存并關(guān)閉會(huì)話
    
session_commit();

    
// 使用新的會(huì)話 ID 開始會(huì)話
    
session_id($new_session_id);
    
ini_set('session.use_strict_mode'0);
    
session_start();
    
ini_set('session.use_strict_mode'1);
    
    
// 新的會(huì)話不需要這 2 個(gè)數(shù)據(jù)了
    
unset($_SESSION['destroyed']);
    unset(
$_SESSION['new_session_id']);
}
?>

參見