設計目標
- 統一讀取 `$_GET`、`$_POST`、`$_COOKIE` (GPC)
- 自動處理 `magic_quotes_gpc` / `magic_quotes_sybase` / `magic_quotes_runtime` 歷史遺留
- 可選移除 HTML 標籤防 XSS
- 編碼轉換預留介面
完整函數庫
<?php
// 來源常數
define('INPUT_GET', 0x0101);
define('INPUT_POST', 0x0102);
define('INPUT_GPC', 0x0103); // POST > GET > COOKIE 優先序
/**
* 讀取並淨化輸入值
* @param string $field 欄位名
* @param int $source INPUT_GET / INPUT_POST / INPUT_GPC
* @param bool $allowHtml 是否允許 HTML 標籤 (預設 false 移除)
* @param string $charset 目標編碼 (預設 null 不轉碼)
* @return string|null 淨化後字串,不存在回傳 null
*/
function getInputValue(string $field, int $source, bool $allowHtml = false, ?string $charset = null): ?string {
$value = null;
// 依優先序取值
if ($source === INPUT_GET && isset($_GET[$field])) {
$value = $_GET[$field];
} elseif ($source === INPUT_POST && isset($_POST[$field])) {
$value = $_POST[$field];
} elseif ($source === INPUT_GPC) {
if (isset($_POST[$field])) $value = $_POST[$field];
elseif (isset($_GET[$field])) $value = $_GET[$field];
elseif (isset($_COOKIE[$field])) $value = $_COOKIE[$field];
}
if ($value === null || $value === '') return $value;
// 1. 處理魔術引號 (PHP 5.4 已移除,但舊專案相容)
if (ini_get('magic_quotes_sybase')) {
$value = str_replace("''", "'", $value);
} elseif (get_magic_quotes_gpc() || get_magic_quotes_runtime()) {
$value = stripslashes($value);
}
// 2. 移除 HTML 標籤 (預設開啟)
if (!$allowHtml) {
$value = strip_tags($value);
}
// 3. 編碼轉換 (預留)
if ($charset && function_exists('mb_convert_encoding')) {
$value = mb_convert_encoding($value, $charset, 'auto');
}
return $value;
}
// 陣列版:遞歸處理整個 $_POST 等
function filterInputArray(array $source, bool $allowHtml = false): array {
$result = [];
foreach ($source as $k => $v) {
if (is_array($v)) {
$result[$k] = filterInputArray($v, $allowHtml);
} else {
// 同樣處理魔術引號與 strip_tags
if (ini_get('magic_quotes_sybase')) $v = str_replace("''", "'", $v);
elseif (get_magic_quotes_gpc() || get_magic_quotes_runtime()) $v = stripslashes($v);
if (!$allowHtml) $v = strip_tags($v);
$result[$k] = $v;
}
}
return $result;
}
// 使用範例
$uid = getInputValue('_uid', INPUT_GET); // 從 GET 取得,已 strip_tags
$comment = getInputValue('comment', INPUT_POST, true); // 允許 HTML (如富文本編輯器)
$allPost = filterInputArray($_POST); // 批次淨化整個 POST
?>
現代專案建議替代方案
| 需求 | 推薦工具 |
| 表單驗證 + 過濾 | Respect/Validation, Laravel Validator, Symfony Validator |
| HTML 過濾 (白名單) | HTMLPurifier (唯一嚴格安全) |
| 輸出編碼 (XSS 防護) | 模板引擎自動逃逸 (Twig, Blade, Latte) 或 htmlspecialchars |
| CSRF 保護 | 同源檢查 + CSRF Token (框架內建) |
核心原則
- 輸入過濾 ≠ 輸出安全:過濾只能減少髒資料,XSS 防護**必須在輸出時**依上下文 (HTML/JS/CSS/URL) 編碼
- 不要嘗試「通用過濾器」攔截所有攻擊:資料用途不同,編碼規則不同
- 資料庫防注入:唯有**預處理語句 (Prepared Statements)** 有效,過濾器無法保證
- 上一篇文章: PHP <code>sprintf()</code> 格式化字串完整指南
- 下一篇文章: PHP 刪除陣列指定元素並重建索引:<code>array_splice()</code> 最佳實務
Copyright ©
程式碼之家 All Rights Reserved