許多開發者僅使用 unset($_SESSION) 或 session_destroy(),導致 Session ID 殘留於客戶端 Cookie,或伺服器端 Session 檔案未即時清除。本文說明完整的四步驟銷毀流程,確保用戶徹底登出。
session_start() 初始化,首次訪問生成唯一 Session ID,存於客戶端 Cookie(預設名 PHPSESSID)。session.save_path)。session_id(session.use_trans_sid)。<?php
// 1. 必須先啟動 Session
session_start();
// 2. 清空伺服器端 $_SESSION 陣列
$_SESSION = array(); // 或 $_SESSION = []; (PHP 5.4+)
// 3. 刪除客戶端 Session Cookie
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(
session_name(), // Cookie 名稱 (預設 PHPSESSID)
'', // 空值
time() - 42000, // 過期時間設為過去
$params["path"], // 路徑
$params["domain"], // 域名
$params["secure"], // 是否僅 HTTPS
$params["httponly"] // HttpOnly 標記
);
}
// 4. 徹底銷毀伺服器端 Session 資料與 ID
session_destroy(); // 刪除 Session 檔案並重置內部狀態
?>
| 錯誤寫法 | 後果 | 正確做法 |
|---|---|---|
unset($_SESSION) | 銷毀變量本身,導致後續 $_SESSION = [] 報錯,且不清除 Session 資料 | $_SESSION = [] |
僅 session_destroy() | 當前請求 $_SESSION 仍可讀,Cookie 未刪除,用戶重新整理可能恢復 Session | 先清空陣列、刪 Cookie、再 destroy |
setcookie(session_name(), '', time()-3600) 缺少 path/domain | 若網站部署在子目錄或多子域,Cookie 刪除失效 | 使用 session_get_cookie_params() 取得完整參數 |
在主域名 .example.com 設定 Cookie,登出時需同步刪除所有子域 Cookie:
setcookie(session_name(), '', time()-3600, '/', '.example.com', true, true);
若使用 session_set_save_handler() 存入 Redis/MySQL,session_destroy() 會自動呼叫 destroy() 回調刪除對應記錄,流程同上。
登出操作應使用 POST 表單或攜帶 CSRF Token,避免惡意連結誘導用戶登出。
function session_logout() {
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$_SESSION = [];
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
session_destroy();
}
在所有需要登出的頁面引入並呼叫 session_logout(),即可確保 Session 徹底銷毀,保障用戶帳號安全。