<?php
// 1. 初始化 (每個腳本最開頭,輸出前)
session_start();
// 2. 寫入資料
$_SESSION['user_id'] = 12345;
$_SESSION['username'] = 'john_doe';
$_SESSION['permissions'] = ['read', 'write', 'admin'];
// 3. 讀取資料
$userId = $_SESSION['user_id'] ?? null;
$username = $_SESSION['username'] ?? 'Guest';
$isAdmin = in_array('admin', $_SESSION['permissions'] ?? []);
// 4. 刪除單一鍵
unset($_SESSION['temp_data']);
// 5. 清空所有 Session 資料
$_SESSION = []; // 或 session_unset()
// 6. 徹底銷毀 Session (登出流程)
session_unset(); // 清空 $_SESSION
session_destroy(); // 刪除伺服器端儲存檔案
// 建議同步清除 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']
);
}
// 7. 取得 Session ID
$sid = session_id(); // 字串
// 或常數 SID (未啟用 Cookie 時包含 "PHPSESSID=xxx")
?>
<?php
// login.php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
// 驗證邏輯 (示意:實際應用參考 PDO + password_verify)
$user = [
'id' => 1,
'username' => 'admin',
'password_hash' => password_hash('123456', PASSWORD_DEFAULT)
];
if ($username === $user['username'] && password_verify($password, $user['password_hash'])) {
// 關鍵:登入成功後重新生成 Session ID 防固定攻擊
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
header('Location: dashboard.php');
exit;
}
$error = '帳號或密碼錯誤';
}
?>
<form method="post">
<input name="username" placeholder="帳號" required>
<input name="password" type="password" placeholder="密碼" required>
<button type="submit">登入</button>
<?php if (!empty($error)) echo "<p class='error'>$error</p>"; ?>
</form>
<?php
// dashboard.php (需登入頁面)
session_start();
if (empty($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
?>
<h1>歡迎, <?= htmlspecialchars($_SESSION['username']) ?></h1>
<a href="logout.php">登出</a>
<?php
// logout.php
session_start();
$_SESSION = [];
session_destroy();
header('Location: login.php');
?>
| 設定 | 建議值 | 說明 |
|---|---|---|
| session.use_strict_mode | 1 | 拒絕未初始化的 Session ID,防固定攻擊 |
| session.use_only_cookies | 1 | 僅接受 Cookie 傳遞 ID,禁用 URL 重寫 |
| session.cookie_httponly | 1 | JavaScript 無法讀取 Session Cookie |
| session.cookie_secure | 1 | 僅 HTTPS 傳輸 Cookie (需 SSL) |
| session.cookie_samesite | Lax | CSRF 保護 (Strict 可能影響外部連結登入) |
| session.gc_maxlifetime | 1440 | 垃圾回收壽命 (秒),配合 GC 機率 |
| session.save_path | /var/lib/php/sessions | 儲存目錄,高並發建議分層 "2;/path" |
<?php
// 實作 SessionHandlerInterface
class PdoSessionHandler implements SessionHandlerInterface
{
private $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
// 建表: CREATE TABLE sessions (id VARCHAR(128) PRIMARY KEY, data TEXT, expiry INT)
}
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 = ? AND expiry > ?");
$stmt->execute([$id, time()]);
return $stmt->fetchColumn() ?: '';
}
public function write($id, $data) {
$expiry = time() + ini_get('session.gc_maxlifetime');
$stmt = $this->pdo->prepare("
INSERT INTO sessions (id, data, expiry) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE data = VALUES(data), expiry = VALUES(expiry)
");
return $stmt->execute([$id, $data, $expiry]);
}
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 PdoSessionHandler($pdo);
session_set_save_handler($handler, true);
session_start();
?>
Session 是 PHP 狀態管理的基石,正確初始化、安全配置與銷毀流程,能有效防範 Session 劫持、固定攻擊與資料洩漏。