Session 是 PHP 實現有狀態會話的核心機制,廣泛應用於用戶登入狀態維持、購物車、權限控制等場景。本文系統梳理 Session 核心操作、常見陷阱,並以「管理員登入驗證」為例展示完整實戰流程。
| 操作 | 代碼 | 說明 |
|---|---|---|
| 啟動 | session_start(); | 每個腳本最開頭呼叫,必須在任何輸出前 |
| 寫入 | $_SESSION['key'] = $value; | 支援陣列、物件(需實現 Serializable) |
| 讀取 | $val = $_SESSION['key'] ?? null; | 使用 null 合併運算子避免 Notice |
| 判斷存在 | isset($_SESSION['key']) | 不觸發 Notice |
| 判斷為空 | empty($_SESSION['key']) | 包含未設定、null、空字串、0、false |
| 刪除單鍵 | unset($_SESSION['key']); | |
| 銷毀整個 Session | session_destroy(); | 僅刪除伺服器端資料,客戶端 Cookie 需另行清除 |
| 重新生成 ID | session_regenerate_id(true); | 防止 Session Fixation 攻擊,登入成功後必呼叫 |
// 安全相關
ini_set('session.cookie_httponly', 1); // 禁止 JS 讀取 Cookie
ini_set('session.cookie_secure', 1); // 僅 HTTPS 傳輸(生產環境必開)
ini_set('session.use_strict_mode', 1); // 拒絕未初始化的 Session ID
ini_set('session.cookie_samesite', 'Lax'); // CSRF 防護
// 效能相關
ini_set('session.gc_maxlifetime', 7200); // 垃圾回收壽命(秒)
ini_set('session.save_path', '/var/lib/php/sessions'); // 自定義存儲路徑(需權限)
<!-- login.php -->
<form action="checklogin.php" method="post">
<div>
<label>用戶名:<input type="text" name="username" required></label>
</div>
<div>
<label>密碼:<input type="password" name="password" required></label>
</div>
<button type="submit">登入</button>
</form>
<?php
// checklogin.php
require_once 'config/db.php';
session_start();
// 1. 獲取並驗證輸入
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
if (!$username || !$password) {
exit(json_encode(['code' => 400, 'msg' => '用戶名密碼不能為空']));
}
// 2. 查詢用戶(預處理防注入)
$stmt = $mysqli->prepare("SELECT id, username, password_hash FROM admin WHERE username = ?");
$stmt->bind_param('s', $username);
$stmt->execute();
$user = $stmt->get_result()->fetch_assoc();
if (!$user) {
exit(json_encode(['code' => 401, 'msg' => '用戶不存在']));
}
// 3. 驗證密碼(使用 password_hash/password_verify)
if (!password_verify($password, $user['password_hash'])) {
exit(json_encode(['code' => 401, 'msg' => '密碼錯誤']));
}
// 4. 登入成功:重新生成 Session ID、寫入用戶標識
session_regenerate_id(true);
$_SESSION['admin_id'] = $user['id'];
$_SESSION['admin_name'] = $user['username'];
$_SESSION['login_time'] = time();
// 5. 返回成功
echo json_encode(['code' => 200, 'msg' => '登入成功', 'redirect' => 'index.php']);
// 或 header('Location: index.php');
<?php
// auth.php - 所有受保護頁面 require_once
session_start();
if (empty($_SESSION['admin_id'])) {
// AJAX 請求返回 JSON,普通請求跳轉登入頁
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
header('Content-Type: application/json');
exit(json_encode(['code' => 401, 'msg' => '未登入或登入過期']));
}
header('Location: login.php');
exit;
}
// 可選:檢查權限等級
// if ($_SESSION['admin_level'] < REQUIRED_LEVEL) { exit('權限不足'); }
<?php
// logout.php
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();
header('Location: login.php');
session_start() 在最頂端。session.save_path 目錄權限、磁碟空間、gc_maxlifetime 過短、多伺服器未共享 Session 存儲(需用 Redis/Memcached)。session_write_close() 釋放鎖。session.cookie_domain = '.example.com'。Session 是 PHP 會話管理的基石。掌握 session_start() 時機、安全配置、密碼驗證最佳實踐、登入/登出完整流程,並理解常見坑點與分散式擴展方案,是合格 PHP 後端工程師的必備技能。本文提供的範本代碼可直接作為專案 Auth 模組的基礎骨架。