使用 Session 管理用戶登入狀態時,登出操作看似簡單,但處理不當容易導致「框架頁面內跳轉」或「Session 殘留」等問題。本文梳理標準登出流程,並針對一般頁面與框架頁面提供最佳實踐代碼。
session_start() 必須在任何輸出前調用。session_destroy() 刪除伺服器端 Session 檔案,但 $_SESSION 變數在當前請求中仍可用。$_SESSION = [] 確保當前請求不再讀到舊資料。setcookie(session_name(), '', time()-3600, '/') 徹底清除客戶端 Cookie。header() 因前有輸出失效。<?php
session_start();
// 1. 清空陣列
$_SESSION = [];
// 2. 刪除伺服器端 Session 檔案
session_destroy();
// 3. 刪除客戶端 Cookie(可選)
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params['path'], $params['domain'],
$params['secure'], $params['httponly']
);
}
?>
<script>
alert('已成功登出!');
location.href = 'login.php';
</script>
若登出頁面嵌套在 <iframe> 或 <frame> 中,使用 location.href 只會在框架內跳轉,導致「頁中頁」體驗極差。必須使用 parent.location.href 或 top.location.href 強制頂層頁面跳轉。
<?php
session_start();
$_SESSION = [];
session_destroy();
// 刪除 Session Cookie
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params['path'], $params['domain'],
$params['secure'], $params['httponly']
);
}
// 輸出跳轉腳本,針對框架頁面
echo "<script>alert('已成功登出!'); parent.location.href = 'login.php';</script>";
?>
<?php
/**
* 統一登出處理
* @param string $redirectUrl 登出後導向網址
* @param bool $isFrame 是否在框架/iframe 中
*/
function logout(string $redirectUrl = 'login.php', bool $isFrame = false): never {
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$_SESSION = [];
session_destroy();
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params['path'], $params['domain'],
$params['secure'], $params['httponly']
);
}
// 防止輸出緩衝導致 header 失效,統一用 JS 跳轉
$target = $isFrame ? "parent.location.href" : "location.href";
echo "<script>alert('已成功登出!'); {$target} = '" . htmlspecialchars($redirectUrl, ENT_QUOTES) . "';</script>";
exit;
}
// 使用範例
// 一般頁面:logout();
// 框架頁面:logout('login.php', true);
?>
Headers already sent 警告。$_SESSION 仍保留,務必手動清空。登出後建議實作 CSRF 保護 與 防止會話固定攻擊:登入時重新生成 Session ID(session_regenerate_id(true)),登出時徹底銷毀。若系統支援「全部裝置登出」,需在資料庫維護用戶的有效 Session 列表或版本號,登出時標記失效。
掌握這些細節,能讓你的登出功能在單頁、多頁、框架頁等各種場景下都表現穩健專業。