(PHP 4 >= 4.3.2, PHP 5, PHP 7, PHP 8)
session_regenerate_id — 使用新生成的會(huì )話(huà) ID 更新現有會(huì )話(huà) ID
$delete_old_session
= false
): boolsession_regenerate_id() 在不修改當前會(huì )話(huà)中數據的前提下使用新的 ID 替換原有會(huì )話(huà) ID。
如果啟用了 session.use_trans_sid 選項, 那么必須在調用 session_regenerate_id() 函數之后開(kāi)始進(jìn)行輸出工作, 否則會(huì )導致使用原有的會(huì )話(huà) ID。
當前的 session_regenerate_id 并沒(méi)有很好的處理在諸如移動(dòng)數據網(wǎng)絡(luò )和 WiFi 網(wǎng)絡(luò )不穩定的場(chǎng)景。 因此,調用 session_regenerate_id 函數 可能會(huì )導致會(huì )話(huà)丟失。
你不應該直接銷(xiāo)毀舊的會(huì )話(huà)所關(guān)聯(lián)的數據, 而是應該使用時(shí)間戳機制來(lái)控制對于已經(jīng)失效的會(huì )話(huà) ID 的訪(fǎng)問(wèn)。 否則,可能會(huì )在并發(fā)訪(fǎng)問(wèn)的場(chǎng)景下導致會(huì )話(huà)數據不一致、 會(huì )話(huà)丟失等情況,甚至可能引發(fā)客戶(hù)端(瀏覽器)創(chuàng )建很多無(wú)用的會(huì )話(huà) ID。 但是,另外一方面來(lái)講,立即刪除會(huì )話(huà)中的數據 可以防止會(huì )話(huà)劫持攻擊。
delete_old_session
是否刪除原 ID 所關(guān)聯(lián)的會(huì )話(huà)存儲文件。 如果你需要避免會(huì )話(huà)并發(fā)訪(fǎng)問(wèn)沖突,那么不應該立即刪除會(huì )話(huà)中的數據。 如果你需要防止會(huì )話(huà)劫持攻擊,那么可以立即刪除會(huì )話(huà)數據。
成功時(shí)返回 true
, 或者在失敗時(shí)返回 false
。
示例 #1 A session_regenerate_id() 示例
<?php
// 注意:下列不是完整的代碼,只是一個(gè)示例
session_start();
// 檢查會(huì )話(huà)被銷(xiāo)毀的時(shí)間戳
if (isset($_SESSION['destroyed'])
&& $_SESSION['destroyed'] < time() - 300) {
// 通常不會(huì )發(fā)生這種情況。如果發(fā)生,那么可能是由于不穩定的網(wǎng)絡(luò )狀況或者被攻擊導致的
// 移除用戶(hù)會(huì )話(huà)中的認證信息
remove_all_authentication_flag_from_active_sessions($_SESSION['userid']);
throw(new DestroyedSessionAccessException);
}
$old_sessionid = session_id();
// 設置會(huì )話(huà)銷(xiāo)毀時(shí)間戳
$_SESSION['destroyed'] = time(); // 從 PHP 7.0.0 開(kāi)始, session_regenerate_id() 會(huì )自動(dòng)保存會(huì )話(huà)數據
// 如果直接調用 session_regenerate_id() 函數可能會(huì )導致會(huì )話(huà)丟失的情況,
// 參見(jiàn)下面的例程
session_regenerate_id();
// 新創(chuàng )建的會(huì )話(huà)不需要時(shí)間戳
unset($_SESSION['destroyed']);
$new_sessionid = session_id();
echo "Old Session: $old_sessionid<br />";
echo "New Session: $new_sessionid<br />";
print_r($_SESSION);
?>
當前的會(huì )話(huà)模塊未能很好的處理在網(wǎng)絡(luò )不穩定的時(shí)候導致會(huì )話(huà)丟失的場(chǎng)景。 你需要自行管理會(huì )話(huà) ID 避免調用 session_regenerate_id 導致會(huì )話(huà)丟失。
示例 #2 Avoiding lost session by session_regenerate_id()
<?php
// 注意:下列不是完整的代碼,只是一個(gè)示例
// my_session_start() 和 my_session_regenerate_id()
// 函數可以避免在網(wǎng)絡(luò )不穩定的情況下導致會(huì )話(huà)丟失的問(wèn)題。
// 并且還可以避免用戶(hù)會(huì )話(huà)被攻擊者利用
function my_session_start() {
session_start();
if (isset($_SESSION['destroyed'])) {
if ($_SESSION['destroyed'] < time()-300) {
// 通常不會(huì )發(fā)生這種情況。如果發(fā)生,那么可能是由于不穩定的網(wǎng)絡(luò )狀況或者被攻擊導致的
// 移除用戶(hù)會(huì )話(huà)中的認證信息
remove_all_authentication_flag_from_active_sessions($_SESSION['userid']);
throw(new DestroyedSessionAccessException);
}
if (isset($_SESSION['new_session_id'])) {
// 尚未完全過(guò)期,可能是由于網(wǎng)絡(luò )不穩定引起的。
// 嘗試再次設置正確的會(huì )話(huà) ID cookie。
// 注意:如果你需要移除認證標記,那么不要嘗試再次設置會(huì )話(huà) ID。
session_commit();
session_id($_SESSION['new_session_id']);
// 現在有了新的會(huì )話(huà) ID 了。
session_start();
return;
}
}
}
function my_session_regenerate_id() {
// 如果由于不穩定的網(wǎng)絡(luò )導致沒(méi)有創(chuàng )建會(huì )話(huà) ID,
// 那么就創(chuàng )建一個(gè)
$new_session_id = session_create_id();
$_SESSION['new_session_id'] = $new_session_id;
// 設置銷(xiāo)毀時(shí)間戳
$_SESSION['destroyed'] = time();
// 保存并關(guān)閉會(huì )話(huà)
session_commit();
// 使用新的會(huì )話(huà) ID 開(kāi)始會(huì )話(huà)
session_id($new_session_id);
ini_set('session.use_strict_mode', 0);
session_start();
ini_set('session.use_strict_mode', 1);
// 新的會(huì )話(huà)不需要這 2 個(gè)數據了
unset($_SESSION['destroyed']);
unset($_SESSION['new_session_id']);
}
?>