首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 正則過濾特殊字符:保留中英數、精準攔截危險符號

     編輯:PHP 相關知識

用戶輸入(用戶名、暱稱、評論)需過濾特殊符號,防 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))
  1. 分組錯誤: | 優先級最低,導致 ]|\[|\/|\\\|\"|\| 被視為獨立分支,實際匹配邏輯混亂。
  2. 元字符未轉義: [ ] ^ $ . * + ? { } ( ) | \ / 在字符類外需轉義,內部 ] \ ^ - 需轉義或放安全位置。
  3. 缺少 Unicode 支持: 無 /u 修飾符,中文按字節匹配易誤傷。
  4. 過度攔截: 連合法標點(如郵箱中的 @ .、數學表達式中的 + - * /)全攔截,業務可用性極差。

最佳實踐原則

  1. 輸入端白名單驗證: 根據業務定義允許字符集(用戶名最嚴格,評論最寬鬆)。
  2. 存儲端原樣存儲: 數據庫用 utf8mb4,參數化查詢防 SQL 注入。
  3. 輸出端語境轉義: HTML 輸出 htmlspecialchars(),JS 輸出 json_encode(),URL 輸出 urlencode(),Shell 輸出 escapeshellarg()。
  4. 不要試圖用一個正則解決所有場景: 不同字段不同規則,分散在各表單驗證類中。

通用「安全字符串」過濾器(兜底)

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 安全的正道。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved