在單點登入(SSO)、跨域共享 Session、或第三方整合場景中,常需根據外部傳入的 Session ID 恢復使用者會話。PHP 透過 session_id() 函數即可實現此需求。
<?php
// 從 GET 參數獲取外部 Session ID
if (isset($_GET["se"])) {
$se = $_GET["se"];
} else {
exit("缺少 Session ID 參數");
}
if (!empty($se)) {
echo "接收到的 Session ID: {$se}
";
// 關鍵:必須在 session_start() 之前設定
session_id($se);
session_start();
echo "當前 Session ID: " . session_id() . "
";
// 讀取 Session 資料驗證
if (isset($_SESSION['h'])) {
echo "Session 資料 [h]: " . $_SESSION['h'];
} else {
echo "Session 中無 'h' 鍵值";
}
}
session_id() 必須在 session_start() 之前 呼叫。若順序顛倒,PHP 會拋出警告且設定無效。
建議加入格式驗證,防止注入攻擊:
// Session ID 僅允許英數字、逗號、減號
if (!preg_match('/^[a-zA-Z0-9,\-]+$/', $se)) {
die("非法的 Session ID 格式");
}
| 風險 | 說明 | 防範措施 |
|---|---|---|
| Session Fixation | 攻擊者強制受害者使用已知 Session ID | 登入後呼叫 session_regenerate_id(true) 重新生成 |
| Session Hijacking | 竊取 Session ID 冒充使用者 | 啟用 HTTPS、設定 session.cookie_secure=1、session.cookie_httponly=1 |
| URL 洩漏 | Session ID 出現在 URL、Referer、日誌中 | 優先使用 Cookie 傳遞、設定 session.use_only_cookies=1 |
<?php
function receiveExternalSession($externalSid) {
// 1. 格式驗證
if (!preg_match('/^[a-zA-Z0-9,\-]{26,}$/', $externalSid)) {
throw new InvalidArgumentException("Invalid session ID format");
}
// 2. 設定安全 Cookie 參數(需在 session_start 前)
ini_set('session.cookie_httponly', '1');
ini_set('session.cookie_secure', '1'); // 僅 HTTPS
ini_set('session.use_only_cookies', '1');
ini_set('session.use_strict_mode', '1'); // PHP 5.5+
// 3. 設定外部 Session ID
session_id($externalSid);
session_start();
// 4. 驗證 Session 有效性(檢查關鍵資料是否存在)
if (!isset($_SESSION['user_id'], $_SESSION['login_time'])) {
session_destroy();
throw new RuntimeException("Session data invalid or expired");
}
// 5. 關鍵:權限提升後立即重新生成 Session ID 防止 Fixation
session_regenerate_id(true);
return $_SESSION['user_id'];
}
PHP 修改 Session ID 機制簡單直接,但涉及會話安全核心。實作時務必嚴格驗證輸入、啟用安全 Cookie 設定、並在權限變更時重新生成 Session ID。現代應用建議改用 JWT、OAuth 2.0 等無狀態認證方案,降低 Session 管理複雜度與風險。