HTTP 協定本質上是無狀態的,Session 機制透過在伺服器端儲存使用者資料,並以唯一識別碼(Session ID)關聯客戶端,解決了跨請求的狀態保持問題。本文系統整理 Session 核心操作與實務應用。
PHPSESSID)或 URL 參數傳遞給客戶端關鍵規則: session_start() 必須在任何輸出(HTML、空白、BOM)之前呼叫。
<?php
// 必須在最頂端,甚至在 <html> 之前
session_start();
?>
<!DOCTYPE html>
<html>
<head><title>Session Demo</title></head>
<body>...</body>
</html>
使用超全域陣列 $_SESSION:
<?php
session_start();
// 寫入
$_SESSION['username'] = 'john_doe';
$_SESSION['login_time'] = time();
$_SESSION['permissions'] = ['read', 'write'];
// 讀取
if (isset($_SESSION['username'])) {
echo "歡迎回來,{$_SESSION['username']}";
echo "登入時間:" . date('Y-m-d H:i:s', $_SESSION['login_time']);
}
?>
<?php
session_start();
if (isset($_SESSION['views'])) {
$_SESSION['views']++;
} else {
$_SESSION['views'] = 1;
}
echo "您是第 {$_SESSION['views']} 次瀏覽本頁面。";
?>
<?php
session_start();
unset($_SESSION['temp_data']); // 釋放單一變數
?>
<?php
session_start();
// 1. 刪除所有 session 變數
$_SESSION = array();
// 2. 刪除 session cookie(若使用 cookie 傳遞 ID)
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// 3. 銷毀伺服器端 session 資料
session_destroy();
header("Location: login.php");
exit;
?>
<?php
class DatabaseSessionHandler implements SessionHandlerInterface {
private $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function open($savePath, $sessionName) { return true; }
public function close() { return true; }
public function read($id) {
$stmt = $this->pdo->prepare("SELECT data FROM sessions WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetchColumn() ?: '';
}
public function write($id, $data) {
$stmt = $this->pdo->prepare("REPLACE INTO sessions (id, data, expiry) VALUES (?, ?, ?)");
return $stmt->execute([$id, $data, time() + ini_get('session.gc_maxlifetime')]);
}
public function destroy($id) {
$stmt = $this->pdo->prepare("DELETE FROM sessions WHERE id = ?");
return $stmt->execute([$id]);
}
public function gc($maxlifetime) {
$stmt = $this->pdo->prepare("DELETE FROM sessions WHERE expiry < ?");
return $stmt->execute([time()]);
}
}
$handler = new DatabaseSessionHandler($pdo);
session_set_save_handler($handler, true);
session_start();
?>
| 設定項 | 建議值 | 說明 |
|---|---|---|
| session.gc_maxlifetime | 1440 (24分鐘) | 資料最大存活秒數,超過視為垃圾回收 |
| session.cookie_lifetime | 0 | 0 表示瀏覽器關閉即過期(會話級 Cookie) |
| session.cookie_httponly | 1 | 防止 JavaScript 存取 Cookie,緩解 XSS |
| session.cookie_secure | 1 (HTTPS 環境) | 僅透過 HTTPS 傳輸 Cookie |
| session.use_strict_mode | 1 | 拒絕未初始化的 Session ID,防止固定攻擊 |
| session.sid_length | 32 | Session ID 長度,越長越安全 |
session_regenerate_id(true)session_start() 是否在所有頁面頂端調用;Cookie 是否被瀏覽器阻擋;session.save_path 目錄是否可寫session_write_close() 釋放鎖Session 是 PHP 狀態管理的核心,理解其運作機制並遵循安全實踐,能構建既便利又安全的使用者體驗。