[英]Properly regenerating session ID's
我正在查看https://www.php.net/manual/en/function.session-regenerate-id.php因為我想學習如何正確處理會話,所以我使用了這個例子:
<?php
// NOTE: This code is not fully working code, but an example!
// my_session_start() and my_session_regenerate_id() avoid lost sessions by
// unstable network. In addition, this code may prevent exploiting stolen
// session by attackers.
function my_session_start() {
session_start();
if (isset($_SESSION['destroyed'])) {
if ($_SESSION['destroyed'] < time()-300) {
// Should not happen usually. This could be attack or due to unstable network.
// Remove all authentication status of this users session.
remove_all_authentication_flag_from_active_sessions($_SESSION['userid']);
throw(new DestroyedSessionAccessException);
}
if (isset($_SESSION['new_session_id'])) {
// Not fully expired yet. Could be lost cookie by unstable network.
// Try again to set proper session ID cookie.
// NOTE: Do not try to set session ID again if you would like to remove
// authentication flag.
session_commit();
session_id($_SESSION['new_session_id']);
// New session ID should exist
session_start();
return;
}
}
}
function my_session_regenerate_id() {
// New session ID is required to set proper session ID
// when session ID is not set due to unstable network.
$new_session_id = session_create_id();
$_SESSION['new_session_id'] = $new_session_id;
// Set destroy timestamp
$_SESSION['destroyed'] = time();
// Write and close current session;
session_commit();
// Start session with new session ID
session_id($new_session_id);
ini_set('session.use_strict_mode', 0);
session_start();
ini_set('session.use_strict_mode', 1);
// New session does not need them
unset($_SESSION['destroyed']);
unset($_SESSION['new_session_id']);
}
?>
我曾嘗試使用該示例並添加它,但我注意到一個問題,每當我登錄會話時,會話就會一次又一次地被擦除,為什么?
代碼最終外觀如下:
<?php
// NOTE: This code is not fully working code, but an example!
// my_session_start() and my_session_regenerate_id() avoid lost sessions by
// unstable network. In addition, this code may prevent exploiting stolen
// session by attackers.
function my_session_start() {
session_start();
if (isset($_SESSION['destroyed'])) {
if ($_SESSION['destroyed'] < time()-300) {
// Should not happen usually. This could be attack or due to unstable network.
// Remove all authentication status of this users session.
remove_all_authentication_flag_from_active_sessions($_SESSION['ID']);
throw(new DestroyedSessionAccessException);
}
if (isset($_SESSION['new_session_id'])) {
// Not fully expired yet. Could be lost cookie by unstable network.
// Try again to set proper session ID cookie.
// NOTE: Do not try to set session ID again if you would like to remove
// authentication flag.
session_commit();
session_id($_SESSION['new_session_id']);
// New session ID should exist
session_start();
return;
}
}
}
function my_session_regenerate_id() {
// New session ID is required to set proper session ID
// when session ID is not set due to unstable network.
$new_session_id = session_create_id();
$_SESSION['new_session_id'] = $new_session_id;
// Set destroy timestamp
$_SESSION['destroyed'] = time();
// Write and close current session;
session_commit();
// Start session with new session ID
session_id($new_session_id);
ini_set('session.use_strict_mode', 0);
session_start();
ini_set('session.use_strict_mode', 1);
// New session does not need them
unset($_SESSION['destroyed']);
unset($_SESSION['new_session_id']);
}
my_session_start();
my_session_regenerate_id();
if(empty($_SESSION['ID'])) header("Location: /login/");
?>
拜托,任何你需要的細節,問我。
回答:
session_regenerate_id(true);
session_regenerate_id();
👍如果您發現此答案很有用,請點贊
session_regenerate_id()<\/a>的 php 手冊中的示例代碼的問題是新的 session_id 還沒有在數據存儲中,所以當 session_start() 被調用時,沒有要加載的會話變量。
我在下面的代碼中通過設置一個變量來解決這個問題
$save_session_vars = $_SESSION;
存儲會話變量,然后在開始新會話時執行相反的操作:
$_SESSION = $save_session_vars;
您可以使用 session_encode() 和 session_decode 來做同樣的事情。
第二個 ini_set 將失敗,因為會話已啟動。 我認為這甚至沒有必要,因為 strict_mode 設置會導致 php 在用戶提供的 session_id 用於啟動會話時檢查會話是否在文件中(正是我們在做什么以及為什么 strict_mode 已關閉)。 一旦會話開始,關閉 strict_mode 可能沒有害處。 但是,在下面的函數中,我再次關閉會話,以便我可以標記對新會話的初始訪問並作為重新生成的會話,因此我繼續在會話關閉時將 strict_mode 重置為 1。
這可能很明顯,但我會注意,如果由於某種原因您的應用程序中有多個 session_start(),則需要將所有內容替換為 regen_session_start() 以便檢查被破壞的標志。
我遇到了這個確切的問題。 php 手冊中用於處理不穩定網絡的“非工作”示例的問題在於它在設置新的 session_id() 后使用了 session_start()。 然而,新的會話還沒有被存儲,所以當會話開始從存儲中讀取會話數據時,它是空的並且有效地刪除了會話數據。 似乎是一罐蠕蟲。 想知道是否有人在這里解決了先有雞還是先有蛋的問題,還是只使用 session_regenerate_id()?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.