PHP Session
Session(會話)是一種在伺服器端儲存使用者資料的機制。與 Cookie 不同,Session 資料存放在伺服器上,只有一個唯一的 Session ID 會傳送給使用者(通常透過 Cookie)。這讓 Session 更適合儲存敏感資料,例如登入狀態、購物車內容、使用者權限等。
開始 Session
使用 session_start() 開始或恢復一個 Session。這個函數必須在任何 HTML 輸出之前呼叫,它會讀取使用者的 Session ID(如果有的話)並載入對應的 Session 資料。
<?php
session_start(); // 必須在任何輸出之前
// 設定 Session 變數
$_SESSION['username'] = 'Alice';
$_SESSION['user_id'] = 123;
// 讀取 Session 變數
echo $_SESSION['username']; // Alice
// 檢查是否存在
if (isset($_SESSION['username'])) {
echo "已登入";
}
?>
登入範例
<?php
session_start();
// 登入
function login(int $userId, string $username): void {
$_SESSION['user_id'] = $userId;
$_SESSION['username'] = $username;
$_SESSION['logged_in'] = true;
$_SESSION['login_time'] = time();
// 重新產生 Session ID 防止 Session Fixation
session_regenerate_id(true);
}
// 檢查是否已登入
function isLoggedIn(): bool {
return isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true;
}
// 取得使用者資訊
function getCurrentUser(): ?array {
if (!isLoggedIn()) {
return null;
}
return [
'id' => $_SESSION['user_id'],
'username' => $_SESSION['username']
];
}
// 登出
function logout(): void {
$_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
當使用者登出或需要清除 Session 時,應該完整地清除 Session 資料、移除 Session Cookie,並銷毀 Session 本身:
<?php
session_start();
// 刪除單一變數
unset($_SESSION['username']);
// 清空所有 Session 變數
$_SESSION = [];
// 銷毀 Session
session_destroy();
?>
Session 設定
可以在 session_start() 之前調整 Session 的行為,例如設定 Cookie 的安全選項、過期時間等:
<?php
// 在 session_start() 之前設定
ini_set('session.cookie_lifetime', 0); // 關閉瀏覽器後過期
ini_set('session.cookie_httponly', 1); // HttpOnly
ini_set('session.cookie_secure', 1); // 只在 HTTPS
ini_set('session.cookie_samesite', 'Lax'); // SameSite
// 或使用 session_set_cookie_params
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax'
]);
session_start();
?>
安全最佳實踐
Session 安全是 Web 應用程式安全的重要環節。以下實踐可以防止 Session 劫持(Session Hijacking)和 Session 固定攻擊(Session Fixation):
<?php
// 1. 重新產生 Session ID
session_start();
if (!isset($_SESSION['initiated'])) {
session_regenerate_id(true);
$_SESSION['initiated'] = true;
}
// 2. 驗證使用者代理
if (isset($_SESSION['user_agent'])) {
if ($_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT']) {
session_destroy();
die('Session hijacking detected');
}
} else {
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
}
// 3. 設定 Session 過期時間
$timeout = 1800; // 30 分鐘
if (isset($_SESSION['last_activity'])) {
if (time() - $_SESSION['last_activity'] > $timeout) {
session_destroy();
header('Location: login.php');
exit;
}
}
$_SESSION['last_activity'] = time();
?>
Flash 訊息
Flash 訊息是一種只顯示一次的 Session 資料,常用於在重新導向後顯示操作結果(如「儲存成功」或「刪除失敗」)。訊息在讀取後會自動移除:
<?php
function setFlash(string $type, string $message): void {
$_SESSION['flash'][$type] = $message;
}
function getFlash(string $type): ?string {
$message = $_SESSION['flash'][$type] ?? null;
unset($_SESSION['flash'][$type]);
return $message;
}
// 使用
setFlash('success', '資料已儲存!');
// 顯示
if ($message = getFlash('success')) {
echo "<div class='alert alert-success'>$message</div>";
}
?>
Session vs Cookie
| 特性 | Session | Cookie |
|---|---|---|
| 儲存位置 | 伺服器 | 瀏覽器 |
| 安全性 | 較高 | 較低 |
| 大小限制 | 無限制 | 約 4KB |
| 生命週期 | 預設至瀏覽器關閉 | 可設定很長 |
| 適用場合 | 敏感資料、登入狀態 | 偏好設定、追蹤 |