早期 PHP 開發常見模式:封裝函數統一處理 $_GET、$_POST、_COOKIE,自動檢測 magic_quotes_gpc 並按需 addslashes() 轉義。本文解析此模式原理與現代替代方案。
<?php
function my_addslashes($string, $force = 0) {
!defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
if (!MAGIC_QUOTES_GPC || $force) {
if (is_array($string)) {
foreach ($string as $key => $val) {
$string[$key] = my_addslashes($val, $force);
}
} else {
$string = addslashes($string);
}
}
return $string;
}
foreach (array('_COOKIE', '_POST', '_GET') as $_request) {
foreach ($$_request as $_key => $_value) {
$_key{0} != '_' && $$_key = my_addslashes($_value); // 變量變量注入符號表
}
}
echo $urls; // 直接使用 $urls 而非 $_GET['urls']
?>
get_magic_quotes_gpc():檢測舊版 PHP 自動轉義開關(PHP 5.4+ 已移除,始終返回 false)addslashes():為單引號、雙引號、反斜杠、Null 字符加反斜杠$$_key 變量變量:將 $_GET['urls'] 注入為 $urls 全局變量(**極不推薦**,污染符號表)$_key{0} != '_':跳過以下劃線開頭的鍵(如 _token)| 問題 | 說明 |
|---|---|
| 安全幻覺 | addslashes() 不防 SQL 注入(多字節繞過),不防 XSS(需 htmlspecialchars())
|
| 上下文缺失 | SQL/HTML/JS/Shell 不同上下文需不同轉義,統一處理必漏洞 |
| 符號表污染 | 變量變量注入導致變量來源不明、覆蓋風險、IDE 無法分析 |
| 魔術引用移除 | PHP 5.4+ 移除 magic_quotes_gpc,代碼邏輯失效
|
| 超全局數組優勢 | $_GET/$_POST 來源明確、可過濾驗證、框架原生支持
|
filter_input()、filter_var()、框架驗證器$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
// HTML
echo htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
// SQL(預處理,無需手動轉義)
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
// JavaScript
echo json_encode($str);
Request 類封裝 $_GET/$_POST/$_FILES/$_COOKIE/$_SERVER// Laravel
$request->input('name');
$request->get('page'); // 僅查詢字符串
$request->post('token'); // 僅 POST 體
// 原生封裝示例
class Request {
public static function get($key, $default = null) {
return $_GET[$key] ?? $default;
}
public static function post($key, $default = null) {
return $_POST[$key] ?? $default;
}
}
歷史代碼反映了早期 PHP「讓開發簡單」的初衷,但現代安全標準要求**輸入驗證、輸出轉義、上下文感知**三位一體,拒絕「一鍵轉義」幻覺。