用戶提交的表單資料若直接輸出至 HTML 頁面,極易導致 XSS(跨站腳本攻擊)、版面錯亂、惡意重導向。本文提供兩種實用的 PHP 過濾函數:基礎版(htmlspecialchars + addslashes)與進階版(正則深度清洗),並解析適用場景與局限。
針對單一參數,自動判斷 GET/POST,處理魔術引號相容,輸出經 htmlspecialchars 轉義的安全字串。
function PostGet($key, $isPost = false) {
if (empty($key)) die('Parameter name required');
$source = $isPost ? $_POST : $_GET;
$raw = $source[$key] ?? '';
// PHP 5.4+ 已移除 magic_quotes_gpc,此判斷僅相容舊環境
if (get_magic_quotes_gpc()) {
$raw = stripslashes($raw); // 先還原
}
// 核心:HTML 實體化,防 XSS
$safe = htmlspecialchars($raw, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// 可選:資料庫層再加 addslashes(不推薦,應用參數化查詢)
// return addslashes($safe);
return $safe;
}
// 使用
$name = PostGet('username'); // GET
$content = PostGet('content', true); // POST
針對富文本、評論等允許部分 HTML 的場景,移除高危標籤(script, iframe, style...)、行內事件(onload, onclick...)、多餘空白。
function uhtml($str) {
if (!is_string($str)) return '';
$patterns = [
'/\s+/' => ' ', // 合併空白
'/<(\/?)(script|iframe|style|html|body|title|link|meta|\?|\%)([^>]*?)>/isU' => '<\1\2\3>', // 全形化危險標籤(或替換為空字串直接刪除)
'/(<[^>]*)on[a-z]+\s*=([^>]*>)/isU' => '\1\2', // 移除行內事件 onxxx=
];
$str = preg_replace(array_keys($patterns), array_values($patterns), $str);
return $str;
}
// 使用
$comment = uhtml($_POST['comment']);
echo $comment; // 安全輸出
| 模式 | 作用 | 說明 |
|---|---|---|
/\s+/ | 合併連續空白 | 防 CSS 注入、版面撐破 |
/<(\/?)(script|iframe|style|html|body|title|link|meta|\?|\%)([^>]*?)>/isU | 匹配高危標籤 | isU 單行模式+非貪婪;替換為全形括號保留可見性,或 '' 直接刪除 |
/(<[^>]*)on[a-z]+\s*=([^>]*>)/isU | 移除行內事件屬性 | onload, onclick, onerror 等 XSS 主要載體 |
htmlspecialchars、JS 用 json_encode、URL 用 urlencode、CSS 用 cssesc),而非入庫前清洗。{{ $var }}), Twig ({{ var|e }}), ThinkPHP ({$var}), Latte 等預設自動 HTML 轉義。Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-xxx'; 徹底禁用內聯腳本、外部非白名單腳本。setcookie(..., true) 防止 JS 竊取 Session ID。| 場景 | 推薦處理 |
|---|---|
| 一般表單欄位(姓名、標題、搜尋關鍵字) | 輸出時 htmlspecialchars($val, ENT_QUOTES, 'UTF-8') |
| 純文字內容(備註、簡介) | 同上,或儲存前 strip_tags + 輸出轉義 |
| 富文本編輯器內容 | HTMLPurifier 清洗 → 儲存 → 輸出時信任(或加 CSP) |
| API JSON 回應 | json_encode 自動處理,勿手工拼接 JSON |
| 舊專案快速修補 | 方案一 PostGet() 統一入口,再逐步遷移至模板自動逃逸 |
PostGet() 適合快速統一入口過濾,uhtml() 適用於需保留部份 HTML 的舊系統。**現代專案請棄用手工過濾,全面採用模板引擎自動逃逸 + CSP + HTMLPurifier** 三層防線,從根源杜絕 XSS。