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

PHP 過濾 HTML 標籤三種方案:正則、狀態機、HTMLPurifier 對比

     編輯:PHP 綜合知識

方案一:正則替換(簡單、性能一般、易漏匹配)

function stripHtmlRegex($str) {
    // 移除註釋
    $str = preg_replace('//s', '', $str);
    // 移除 script/style 及內容
    $str = preg_replace('/<(script|style)[^>]*>.*?<\/\1>/is', '', $str);
    // 移除所有標籤
    $str = preg_replace('/<[^>]+>/', '', $str);
    // 實體解碼
    $str = html_entity_decode($str, ENT_QUOTES, 'UTF-8');
    return trim($str);
}

缺點:無法處理屬性中包含 > 的情況、嵌套標籤、條件註釋、CDATA 等邊界案例。

方案二:字符級狀態機(零依賴、性能較好、邏輯可控)

function stripHtmlStateMachine($str) {
    $len = strlen($str);
    $result = '';
    $inTag = false;
    $tagDepth = 0; // 處理嵌套
    $quoteChar = null; // 處理屬性引號
    
    for ($i = 0; $i < $len; $i++) {
        $ch = $str[$i];
        
        if (!$inTag) {
            if ($ch === '<') {
                // 檢查是否為註釋 
                    if ($i >= 2 && $str[$i-2] === '-' && $str[$i-1] === '-') {
                        // 註釋結束
                    }
                }
            } elseif ($ch === '<') {
                $tagDepth++; // 嵌套標籤(罕見但合法)
            }
        }
    }
    
    return html_entity_decode(trim($result), ENT_QUOTES, 'UTF-8');
}

方案三:HTMLPurifier(企業級、最安全、標準合規)

composer require ezyang/htmlpurifier
require_once 'vendor/autoload.php';

$config = HTMLPurifier_Config::createDefault();
$config->set('Core.Encoding', 'UTF-8');
$config->set('HTML.Doctype', 'HTML 4.01 Transitional');
// 只允許極少標籤
$config->set('HTML.Allowed', 'p,b,i,em,strong,a[href|title],ul,ol,li,br,span[style]');

$purifier = new HTMLPurifier($config);
$cleanHtml = $purifier->purify($dirtyHtml);

方案對比

維度正則狀態機HTMLPurifier
安全性低(易繞過 XSS)中(需自行完善)極高(白名單機制)
性能中高低(解析開銷大)
依賴無無Composer 包
維護成本低中低(庫維護)
適用場景簡單清洗、內部數據高性能、無依賴環境用戶輸入、富文本、CMS、論壇

實戰建議

  1. 用戶提交的富文本:必須用 HTMLPurifier,配置白名單標籤/屬性,防 XSS。
  2. 內部生成/可信數據清洗:正則或狀態機均可,追求性能用狀態機。
  3. 純文本提取:strip_tags() 內建函數(但不處理實體、script 內容),配合 html_entity_decode()。
  4. 編輯器輸出存儲:存儲前 Purify,輸出時信任(或再次 Purify 防二次注入)。

內建 strip_tags 陷阱

$str = 'Bold';
echo strip_tags($str); // 輸出:alert(1)Bold  ← script 內容未被移除!
// 正確:先移除 script/style 再 strip_tags
$str = preg_replace('/<(script|style)[^>]*>.*?<\/\1>/is', '', $str);
echo strip_tags($str); // 輸出:Bold
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved