超全域陣列在所有作用域自動可見,無需 global 宣告,是 PHP 處理 HTTP 請求、環境資訊、會話狀態的核心介面。本文系統整理九大超全域陣列用途、安全風險與最佳實踐。
| 陣列 | 來源 | 典型用途 | 安全風險 |
|---|---|---|---|
$_GET | URL 查詢字串 | 分頁、搜尋、篩選、靜態連結 | XSS、CSRF、資訊洩露、SQL Injection |
$_POST | HTTP POST Body | 表單提交、API 輸入、狀態變更 | CSRF、XSS、大量資料 DoS |
$_REQUEST | $_GET+$_POST+$_COOKIE | 快速原型(不建議生產) | 來源混淆、Cookie 覆蓋 POST/GET |
$_FILES | multipart/form-data 上傳 | 檔案上傳處理 | 任意檔案上傳、路徑遍歷、MIME 偽裝 |
$_COOKIE | HTTP Cookie 標頭 | 偏好設定、追蹤、記住登入 | XSS 竊取、CSRF、敏感資料洩露 |
$_SESSION | 伺服器端會話儲存 | 使用者狀態、購物車、權限快取 | Session Fixation、Hijacking、資料洩露 |
$_ENV | 環境變數 | 部署設定、密鑰、特徵開關 | 敏感資訊洩露(勿輸出) |
$_SERVER | Web 伺服器環境 | 請求資訊、路徑、標頭、腳本路徑 | 偽造標頭、路徑洩露、內部 IP 洩露 |
$GLOBALS | 全域符號表 | 極少數跨檔案全域狀態 | 命名衝突、隱性耦合、難以測試 |
$_GET / $_POST 安全存取模式<?php
// ❌ 危險:直接使用,未驗證、未轉義
echo $_GET['name'];
// ✅ 安全:過濾輸入、輸出轉義
$name = filter_input(INPUT_GET, 'name', FILTER_SANITIZE_SPECIAL_CHARS);
echo $name; // 已轉義
// ✅ 表單處理:POST-Redirect-GET 防重複提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($email) {
// 處理業務邏輯...
header('Location: success.php');
exit;
}
}
?>
$_FILES 上傳處理標準流程if (isset($_FILES['avatar'])) {
$file = $_FILES['avatar'];
// 檢查錯誤碼
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new RuntimeException('上傳失敗: ' . $file['error']);
}
// 驗證 MIME(需搭配 finfo,不可信任瀏覽器提供的 type)
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($file['tmp_name']);
$allowed = ['image/jpeg', 'image/png', 'image/webp'];
if (!in_array($mime, $allowed, true)) {
throw new RuntimeException('不支援的檔案類型');
}
// 驗證大小
if ($file['size'] > 2 * 1024 * 1024) { // 2MB
throw new RuntimeException('檔案過大');
}
// 安全儲存:隨機檔名、存放非公開目錄
$ext = ['image/jpeg'=>'jpg', 'image/png'=>'png', 'image/webp'=>'webp'][$mime];
$dest = '/var/www/uploads/' . bin2hex(random_bytes(16)) . ".$ext";
if (!move_uploaded_file($file['tmp_name'], $dest)) {
throw new RuntimeException('移動檔案失敗');
}
}
$_SESSION 安全設定<?php
// 必須在任何輸出前呼叫
session_start();
// 安全配置(建議在 php.ini 或啟動腳本集中設定)
ini_set('session.cookie_httponly', '1'); // 阻止 JS 存取
ini_set('session.cookie_secure', '1'); // 僅 HTTPS 傳輸
ini_set('session.use_strict_mode', '1'); // 拒絕未初始化 ID
ini_set('session.cookie_samesite', 'Strict'); // CSRF 防護
// 重新產生 ID 防 Session Fixation
if (!isset($_SESSION['initiated'])) {
session_regenerate_id(true);
$_SESSION['initiated'] = true;
}
// 存取
$_SESSION['user_id'] = 123;
$userId = $_SESSION['user_id'] ?? null;
$_SERVER 關鍵鍵名對照| 鍵名 | 含義 | 可信度 |
|---|---|---|
REQUEST_METHOD | GET/POST/PUT... | 高 |
REQUEST_URI | 完整請求路徑含查詢字串 | 高 |
HTTP_HOST | Host 標頭 | 中(可偽造) |
HTTP_USER_AGENT | User-Agent | 低(可偽造) |
HTTP_REFERER | Referer 標頭 | 低(可偽造/缺失) |
REMOTE_ADDR | 客戶端 IP | 中(代理下需讀 X-Forwarded-For) |
SCRIPT_FILENAME | 執行腳本絕對路徑 | 高 |
DOCUMENT_ROOT | 網站根目錄 | 高 |
$_ENV 與 getenv()<?php
// 讀取環境變數(.env 檔案需搭配 vlucas/phpdotenv 載入)
$dbHost = $_ENV['DB_HOST'] ?? getenv('DB_HOST') ?? 'localhost';
// 生產環境敏感設定務必從環境變數讀取,勿寫死程式碼
function logRequest() {
// 直接可用
$method = $_SERVER['REQUEST_METHOD'];
$ip = $_SERVER['REMOTE_ADDR'];
error_log("[$method] $ip");
}
logRequest(); // 正常運作
$config = ['debug' => true];
function getConfig() {
// ❌ 反模式:隱性依賴全域狀態
return $GLOBALS['config'];
}
// ✅ 良模式:依賴注入
function getConfig(array $config) {
return $config;
}
// 或使用服務容器/單例模式
PHP 4.2 預設關閉、5.4 移除 register_globals。舊碼 echo $username; 直接使用查詢字串變數極度危險,務必改用 $_GET['username']。
filter_input() + htmlspecialchars()。$_REQUEST:明確使用 $_GET/$_POST,避免 Cookie 覆蓋。httponly、secure、samesite、strict_mode。$_ENV + phpdotenv,勿提交 .env 至版控。$GLOBALS、global,改用依賴注入。總結:超全域陣列是 PHP 與外部世界溝通的橋樑。理解各陣列來源、可信度、安全風險,配合「輸入過濾、輸出轉義、最小權限、明確來源」原則,即能建構安全可靠的 Web 應用程式。