雖然現代 PHP 開發強烈建議使用 Prepared Statement(參數綁定) 作為防禦 SQL Injection 的首選,但在維護舊專案或特定情境下,仍需對輸入值做基礎過濾。本文整理一套「關鍵字過濾 + 型別檢查 + 轉義」的防禦組合,作為第二道防線。
class InputFilter {
/**
* 過濾 SQL 與檔案操作關鍵字
* @param string $string
* @return string
*/
private function filter_keyword($string) {
$keyword = 'select|insert|update|delete|\'|/\*|\*/|../|./|union|into|load_file|outfile';
$arr = explode('|', $keyword);
return str_ireplace($arr, '', $string);
}
/**
* 檢查輸入是否為合法整數 ID
* @param mixed $id
* @return int|false
*/
protected function check_id($id) {
$result = false;
if ($id !== '' && !is_null($id)) {
$var = $this->filter_keyword($id);
if ($var !== '' && !is_null($var) && is_numeric($var)) {
$result = intval($var);
}
}
return $result;
}
/**
* 檢查輸入字串並做安全處理
* @param string $string
* @return string|false
*/
protected function check_str($string) {
$result = false;
$var = $this->filter_keyword($string);
if (!empty($var)) {
// 若 magic_quotes_gpc 關閉,手動 addslashes
if (!get_magic_quotes_gpc()) {
$var = addslashes($string);
}
// 過濾 LIKE 萬用字元
$var = str_replace('%', '\%', $var);
$var = str_replace('_', '\_', $var);
// 換行轉
、HTML 特殊字元實體化
$var = nl2br($var);
$var = htmlspecialchars($var);
$result = $var;
}
return $result;
}
}
| 方法 | 適用場景 | 注意事項 |
|---|---|---|
| check_id() | 數值型主鍵、分頁參數、排序欄位 | 回傳 int 或 false,直接可用於 SQL WHERE id = ? |
| check_str() | 搜尋關鍵字、留言內容、姓名等文字欄位 | 已做 htmlspecialchars,輸出到 HTML 安全;但若直接拼 SQL 仍有風險 |
magic_quotes_gpc 自 PHP 5.4 起已移除,舊專案若仍開啟需額外處理 stripslashes()。htmlspecialchars(),防 XSS;輸出到 JS/JSON/CSS 時需對應編碼函式。SELECT, INSERT, UPDATE, DELETE,勿給 DROP, ALTER, GRANT。此類別適合作為舊專案快速加固的過渡方案,新專案請直接採用參數綁定與嚴格的輸入驗證(如 filter_var()、Respect\Validation 等)。