許多開發者為了省去判斷 POST/GET 的程式碼,習慣直接使用 $_REQUEST。但深入分析會發現,$_REQUEST 不僅合併 $_GET 和 $_POST,還包含 $_COOKIE 所有資料,這帶來嚴重的資料來源混淆風險。
建立測試檔 req.php:
<?php
var_dump($_GET['a'], $_POST['a'], $_REQUEST['a']);
?>
<html>
<head><title>demo</title></head>
<body>
<form method='post' action='req.php?a=xxx'>
<input type='hidden' name='a' value='yyy'/>
<input type='submit' name='submit' value='submit'/>
</form>
</body>
</html>
提交表單後輸出:
string(3) "xxx" string(3) "yyy" string(3) "yyy"
$_REQUEST['a'] 取到的是 POST 值 yyy,覆蓋了 GET 的 xxx。
PHP 設定檔 php.ini 中的 variables_order 決定註冊順序與覆蓋優先級:
; This directive describes the order in which PHP registers GET, POST, Cookie,
; Environment and Built-in variables (G, P, C, E & S respectively, often
; referred to as EGPCS or GPC). Registration is done from left to right, newer
; values override older values.
variables_order = "EGPCS"
EGPCS 含義:
$_ENV$_GET$_POST$_COOKIE$_SESSION預設 EGPCS 表示:後註冊的覆蓋先註冊的,故 POST 覆蓋 GET,COOKIE 覆蓋 POST。
$_REQUEST 需合併多個超全域陣列,比直接存取 $_GET/$_POST 慢$_GET['param']、$_POST['param']、$_COOKIE['param']php.ini 設定 request_order = "GP"(排除 Cookie)或框架層面封禁