Web 安全首要原則:永遠不要信任使用者輸入。PHP 提供多層次過濾函式,但濫用、誤用極常見。本文系統歸類六大內建函式、說明適用場景、常見誤區、現代替代方案 (PDO 預處理、HTMLPurifier、驗證器),並提供「輸入驗證 → 處理 → 輸出編碼」三階段防禦模型。
| 函式 | 用途 | 核心邏輯 | 適用場景 | 狀態 |
|---|---|---|---|---|
mysql_real_escape_string() | SQL 字串跳脫 | 對特殊字元加反斜線 | 舊 mysql_* 專用 | 已棄用/移除 (PHP 7.0) |
addslashes() | 通用字串跳脫 | 單引號、雙引號、反斜線、NUL 加反斜線 | 非資料庫字串儲存、舊系統相容 | 不建議用於 SQL |
htmlentities() | 全字元 HTML 實體化 | 所有可轉換字元 → &xxx; | 輸出到 HTML 內容、屬性、JS 字串 | 可用,但較重 |
htmlspecialchars() | 關鍵字元 HTML 實體化 | & < > " ' → 實體 | 輸出到 HTML 體內容/屬性首選 | 推薦 |
strip_tags() | 移除 HTML/PHP 標籤 | 保留允許標籤 (第二參數) | 簡單富文本清理、預覽摘要 | 不安全,無法防 XSS |
intval() / (int) | 強制轉整數 | 截取數字前綴,非數字回 0 | ID、分頁、數量等整數參數 | 推薦 |
// 錯誤:字元集問題、無法防禦多字節注入、雙重跳脫
$safe = addslashes($_GET['id']);
$sql = "SELECT * FROM users WHERE id = '$safe'";
✅ 正確:PDO 預處理 (參數化查詢,資料與程式碼分離)
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]); // 自動處理型別與跳脫
// 錯誤:屬性型 XSS 繞過
//
→ strip_tags 保留 img → XSS 生效
echo strip_tags($input, '
');
✅ 正確:輸出時編碼 (Context-Aware Output Encoding)
echo htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
echo '';
echo '';
PHP 5.4 移除。若舊專案仍依賴,需在入口檔案清理:
if (get_magic_quotes_gpc()) {
$_GET = array_map('stripslashes', $_GET);
$_POST = array_map('stripslashes', $_POST);
$_COOKIE = array_map('stripslashes', $_COOKIE);
}
filter_var(), filter_input(), 表單驗證器。filter_var($email, FILTER_VALIDATE_EMAIL)、(int)$_GET['page']。| 需求 | 推薦工具 | 安裝 |
|---|---|---|
| HTML 安全清理 (允許部分標籤) | HTMLPurifier | composer require ezyang/htmlpurifier |
| 表單/資料驗證 | Symfony Validator, Laravel Validation, Respect/Validation | composer require respect/validation |
| CSRF 保護 | 同站 Cookie (SameSite=Lax/Strict) + CSRF Token | 框架內建 |
| 內容安全政策 | CSP Header | Nginx/Apache/PHP 設定 Header |
// 1. HTML 文字內容
htmlspecialchars($str, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')
// 2. HTML 屬性值 (雙引號包裹)
htmlspecialchars($str, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')
// 3. JavaScript 字串 (單引號包裹)
json_encode($str, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP)
// 4. URL 參數
urlencode($str) // 或 rawurlencode() (RFC 3986)
// 5. CSS 值
// 極少直接輸出,若需用請用專用庫
// 6. SQL (不要手工跳脫!)
$pdo->prepare(...)->execute([$param])
安全不是靠單一函式,而是「驗證輸入、參數化處理、語境編碼輸出」的系統工程。棄用舊函式、擁抱 PDO 與現代模板引擎,才能從根本上阻斷 SQL 注入與 XSS 攻擊面。