萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 過濾清理 HTML、JavaScript、CSS 標籤完整方案

PHP 內容淨化:從基礎函數到企業級 XSS 防護

處理用戶提交的富文本內容時,需根據業務場景選擇適當的清理策略。本文系統梳理 strip_tags、HTML 實體轉義、正則清理、HTMLPurifier 等多層級方案。

一、內置函數快速方案

1. strip_tags() - 保留指定標籤

<?php
$html = '<p>段落</p><script>alert(1)</script><b>粗體</b>';

// 刪除所有標籤
echo strip_tags($html); 
// 輸出:段落alert(1)粗體

// 保留 <p> <b>
echo strip_tags($html, '<p><b>'); 
// 輸出:<p>段落</p>alert(1)<b>粗體</b>

// 保留多個標籤(空格分隔)
echo strip_tags($html, '<p> <b> <i> <br>');
?>

缺陷:不處理屬性(如 onclick)、不修復破損標籤、不處理 CSS/JS 注入。

2. HTML 實體轉義函數對比

函數轉義範圍適用場景備註
htmlspecialchars()& " < >HTML 輸出、屬性值性能最好,推薦默認使用
htmlentities()所有可轉義字符需完全實體化時中文會變實體,源碼難讀
addslashes()' " \ NULL入庫前(已棄用)應用參數化查詢替代
stripslashes()移除反斜杠配合 addslashes魔術引號時代遺物
nl2br()\n → <br>純文本換行轉 HTML不轉義其他字符

3. 輸出安全最佳實踐

<?php
// 輸出到 HTML 內容區域
function h($str) {
    return htmlspecialchars($str, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

// 輸出到 HTML 屬性值(單引號包裹)
function h_attr($str) {
    return htmlspecialchars($str, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

// 輸出到 JavaScript 字符串
function h_js($str) {
    return json_encode($str, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
}

// 使用範例
echo "<div class='".h_attr($userClass)."'>".h($userContent)."</div>";
echo "<script>var msg = ".h_js($userMsg).";</script>";
?>

二、正則清理方案(不推薦生產環境)

警告:正則無法完整解析 HTML,僅適用於簡單、可控的內容清理。

1. 移除 Script/Style/註釋

<?php
function stripScriptsStyles($html) {
    $patterns = [
        '/<script\b[^>]*>.*?<\/script>/is',   // 移除 script
        '/<style\b[^>]*>.*?<\/style>/is',    // 移除 style
        '/<!--.*?-->/s',                      // 移除註釋
    ];
    return preg_replace($patterns, '', $html);
}
?>

2. 移除所有標籤但保留文本

<?php
function stripAllTags($html) {
    // 移除標籤
    $text = preg_replace('/<[^>]+>/', '', $html);
    // 解碼實體
    $text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    // 清理多餘空白
    $text = preg_replace('/\s+/', ' ', $text);
    return trim($text);
}
?>

三、企業級方案:HTMLPurifier

唯一推薦用於生產環境的富文本過濾庫,符合 W3C 標準,防 XSS 攻擊。

安裝與基礎配置

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

$config = HTMLPurifier_Config::createDefault();

// 核心配置
$config->set('HTML.Doctype', 'HTML5');
$config->set('HTML.Allowed', 'p,b,i,em,strong,u,strike,a[href|title],ul,ol,li,br,img[src|alt|width|height],table,thead,tbody,tr,th,td,div[class],span[class]');
$config->set('CSS.AllowedProperties', 'font-family,font-size,color,background-color,text-align,width,height,margin,padding,border');
$config->set('AutoFormat.RemoveEmpty', true);
$config->set('AutoFormat.AutoParagraph', true);

// URI 安全
$config->set('URI.AllowedSchemes', ['http' => true, 'https' => true, 'mailto' => true]);
$config->set('URI.DisableExternalResources', false);

// 緩存配置(生產環境必須)
$config->set('Cache.SerializerPath', __DIR__ . '/storage/cache/htmlpurifier');

$purifier = new HTMLPurifier($config);

$dirtyHtml = '<script>alert(1)</script><p onclick="evil()">安全內容</p><img src=x onerror=alert(2)>';
$cleanHtml = $purifier->purify($dirtyHtml);
// 結果:<p>安全內容</p><img src="x" alt="">
?>

常用允許規則速查

<?php
// 完整允許規則語法
$config->set('HTML.Allowed', '
    a[href|title|target|rel],
    img[src|alt|width|height|class],
    div[class|style],
    span[class|style],
    p[class|style],
    br, hr,
    b, i, em, strong, u, strike, s,
    ul, ol, li,
    table, thead, tbody, tr, th, td,
    h1, h2, h3, h4, h5, h6,
    blockquote, pre, code
');
// 格式:標籤名[屬性1|屬性2|...],多標籤用逗號分隔
?>

四、場景化選型建議

業務場景推薦方案說明
純文本輸入(用戶名、評論)htmlspecialchars()完全轉義,最安全
簡單富文本(允許粗體、換行)strip_tags($html, '<b><i><br>') + htmlspecialchars() 屬性值輕量級,但無法防屬性 XSS
編輯器內容(CKEditor、TinyMCE)HTMLPurifier標準合規、可配置、防 XSS
API 輸出 JSONjson_encode() 含安全標誌前端負責渲染安全
郵件模板HTMLPurifier(郵件模式配置)郵件客戶端兼容性要求高

五、性能優化建議

  • HTMLPurifier 必須啟用緩存(Cache.SerializerPath),首次運行會編譯定義庫
  • 大量內容清理時考慮異步隊列處理
  • 只清理一次:入庫時清理,讀取時直接輸出(或雙重防護:入庫清理 + 輸出轉義)
  • 簡單場景優先用原生函數,避免引入重型庫
copyright © 萬盛學電腦網 all rights reserved