(PHP 4 >= 4.3.2, PHP 5, PHP 7, PHP 8)
session_regenerate_id — 使用新生成的會(huì)話 ID 更新現(xiàn)有會(huì)話 ID
$delete_old_session
= false
): boolsession_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ì)話劫持攻擊。
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']);
}
?>