當 php.ini 設定 register_globals = On 時,`$_GET`、`$_POST`、`$_COOKIE`、`$_SESSION` 同名變數會自動註冊為全域變數(如 `$username`),導致來源混淆、安全性風險。
variables_order = "GPCS"(預設)定義覆蓋優先級:
因此,若一開始就 session_register('username'),Session 變數會覆蓋同名 GET/POST/COOKIE 變數,相對安全。
<?php
session_start();
// 1. 檢查 Session 是否已註冊 username
if (!isset($_SESSION['username'])) {
$_SESSION['username'] = ''; // 初始化
}
// 2. 登入邏輯(示意)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$user = $_POST['username'] ?? '';
$pass = $_POST['password'] ?? '';
// 驗證資料庫...
if ($valid) {
$_SESSION['username'] = $user;
$_SESSION['user_id'] = $uid;
}
}
// 3. 受保護頁面頂部統一檢查
if (empty($_SESSION['username'])) {
header('Location: login.php');
exit;
}
// 後續程式碼可直接使用 $_SESSION['username']
?>
| 建議 | 理由 |
|---|---|
| 關閉 register_globals | PHP 5.4 已移除此選項;舊版必須設 Off,避免變數汙染 |
| 唯一使用 $_SESSION 存取 | 明確來源,不依賴全域變數註冊 |
| 啟用 session.use_only_cookies | 防止 Session ID 透過 URL 傳遞被盜用 |
| 設定 session.cookie_httponly | JavaScript 無法讀取 Session Cookie,緩解 XSS |
| 定期重生 Session ID | session_regenerate_id(true) 於登入成功/權限變更時呼叫 |
| 設定嚴格的 session.save_path | 避免共享主機 Session 檔案被其他用戶讀取 |
Auth::guard()->check()、auth 中介層、加密 Session 驅動。SecurityBundle、Firewall、UserProvider、PasswordHasher。session() 服務、AuthController、Filters。誤區:
session_is_registered('username')可判斷用戶是否登入。
事實:此函式 PHP 5.4 移除;應用isset($_SESSION['username'])或!empty($_SESSION['user_id'])。
理解 register_globals、variables_order、session_register 之間的交互關係,是早期 PHP 開發者避開安全陷阱的關鍵;現代開發請直接遵循「關閉全域註冊、顯式使用超級全域陣列」原則。