用戶輸入(用戶名、暱稱、評論)需過濾特殊符號,防 XSS、SQL 注入、存儲異常。原文正則存在過度匹配、未轉義元字符、未考慮 Unicode 等問題。本文給出生產級白名單/黑名單混合方案。
<?php
function filterUsername(string $input): string {
// 允許:中文、英文、數字、下劃線、連字符、點(長度 2-20)
if (!preg_match('/^[\p{Han}\w.-]{2,20}$/u', $input)) {
throw new InvalidArgumentException('用戶名僅支持中英文、數字、下劃線、點、連字符,長度 2-20 位');
}
return $input;
}
function filterNickname(string $input): string {
// 允許:中文、英文、數字、常見標點、Emoji(長度 1-30)
// \p{P} 標點,\p{So} 符號(含 Emoji),\p{Zs} 空格分隔符
if (!preg_match('/^[\p{Han}\w\s\p{P}\p{So}]{1,30}$/u', $input)) {
throw new InvalidArgumentException('暱稱包含非法字符');
}
// 額外:過濾腳本標簽、SQL 關鍵字(防二次注入)
$input = strip_tags($input);
return $input;
}
function stripDangerousChars(string $input): string {
// 移除:控制字符、NULL 字節、刪除鍵、BOM、零寬字符
$input = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $input); // 控制字符
$input = str_replace("\xEF\xBB\xBF", '', $input); // UTF-8 BOM
$input = preg_replace('/[\x{200B}-\x{200D}\x{FEFF}]/u', '', $input); // 零寬空格/連字符
return $input;
}
// 原文
if(preg_match("/[ '.,:;*?~`!@#$%^&+=)(<>{}]|\]|\[|\/|\\\|\"|\|/",$user))
| 優先級最低,導致 ]|\[|\/|\\\|\"|\| 被視為獨立分支,實際匹配邏輯混亂。[ ] ^ $ . * + ? { } ( ) | \ / 在字符類外需轉義,內部 ] \ ^ - 需轉義或放安全位置。/u 修飾符,中文按字節匹配易誤傷。@ .、數學表達式中的 + - * /)全攔截,業務可用性極差。utf8mb4,參數化查詢防 SQL 注入。htmlspecialchars(),JS 輸出 json_encode(),URL 輸出 urlencode(),Shell 輸出 escapeshellarg()。function sanitizeString(string $input, int $maxLen = 1000): string {
$input = stripDangerousChars($input);
$input = mb_substr($input, 0, $maxLen, 'UTF-8');
$input = strip_tags($input); // 移除 HTML 標簽
return trim($input);
}
拒絕「大雜燴」黑名單正則,擁抱分場景白名單驗證 + 輸出端語境轉義,才是 Web 安全的正道。