register_globals 是 PHP 早期(PHP 4.2 之前)預設開啟的配置指令,將 GET、POST、COOKIE、SESSION、SERVER、ENV 等超全域變數自動註冊為全域變數。此功能已於 PHP 5.4 移除,現代 PHP 開發必須理解其風險並避免依賴。
<!-- 表單範例 --> <form name="frmTest" action="process.php" method="post"> <input type="text" name="user_name"> <input type="password" name="user_pass"> <input type="submit" value="login"> </form>
| 設定 | 接收方式 | 程式碼範例 |
|---|---|---|
| register_globals = Off(預設/現代標準) | 超全域陣列 | $name = $_POST['user_name']; |
| register_globals = On(危險/已移除) | 直接全域變數 | $name = $user_name; |
?is_admin=1 覆蓋內部邏輯變數 $is_admin$authenticated)可被外部注入若必須維護舊代碼,可在共用引入檔(如 config.inc.php)加入模擬代碼:
<?php
if (!ini_get('register_globals')) {
// 依序提取,後者覆蓋前者(模擬 PHP 預設 EGPCS 順序)
extract($_ENV, EXTR_SKIP);
extract($_GET, EXTR_SKIP);
extract($_POST, EXTR_SKIP);
extract($_COOKIE, EXTR_SKIP);
extract($_SERVER, EXTR_SKIP);
if (isset($_SESSION)) extract($_SESSION, EXTR_SKIP);
}
?>
注意:EXTR_SKIP 避免覆蓋既有變數,但無法 100% 重現原始行為,建議逐步重構為顯式超全域陣列存取。
| 來源 | 正確存取方式 | 錯誤示範 |
|---|---|---|
| 表單 POST | $_POST['field'] | $field (需 register_globals=On) |
| URL 參數 | $_GET['param'] | $param |
| Cookie | $_COOKIE['name'] | $name |
| Session | $_SESSION['key'] | session_register('key') (已移除) |
| 伺服器變數 | $_SERVER['HTTP_HOST'] | $HTTP_HOST |
$_REQUEST 合併了 $_GET、$_POST、$_COOKIE(順序受 variables_order 影響),無法判斷資料來源,安全敏感操作(登入、付款、權限變更)嚴禁使用,必須明確指定來源陣列。
<?php
// 方法一:phpinfo()
phpinfo(); // 搜尋 "register_globals"
// 方法二:程式碼檢查
var_dump(ini_get('register_globals')); // '0' 或 '1' (字串)
// 方法三:.htaccess (僅 Apache + mod_php)
php_flag register_globals Off
?>
register_globals = Off$_GET、$_POST、$_COOKIE、$_SESSIONfilter_input()、filter_var()allow_url_include、allow_url_fopen(非必要時)