鍍金池/ 教程/ PHP/ 凈化 HTML 輸入和輸出
驗(yàn)證郵件地址
自動(dòng)加載類
PHP 與 MySQL
緩存 PHP opcode
檢測(cè)一個(gè)值是否為 null 或 false
PHP 標(biāo)簽
從性能角度來(lái)看單引號(hào)和雙引號(hào)
發(fā)送郵件
處理日期和時(shí)間
define() vs. const
配置 Web 服務(wù)器提供 PHP 服務(wù)
PHP 與 UTF-8
我們?cè)谑褂媚膫€(gè)版本的 PHP?
凈化 HTML 輸入和輸出
PHP 與正則表達(dá)式
存儲(chǔ)密碼
PHP 與 Memcached

凈化 HTML 輸入和輸出

對(duì)于簡(jiǎn)單的數(shù)據(jù)凈化,使用 htmlentities() 函數(shù), 復(fù)雜的數(shù)據(jù)凈化則使用 HTML Purifier 庫(kù)

經(jīng) HTML Purifier 4.4.0 測(cè)試

在任何 wbe 應(yīng)用中展示用戶輸出時(shí),首先對(duì)其進(jìn)行“凈化”去除任何潛在危險(xiǎn)的 HTML 是非常必要的。 一個(gè)惡意的用戶可以制作某些 HTML,若被你的 web 應(yīng)用直接輸出,對(duì)查看它的人來(lái)說(shuō)會(huì)很危險(xiǎn)。

雖然可以嘗試使用正則表達(dá)式來(lái)凈化 HTML,但不要這樣做。HTML是一種復(fù)雜的語(yǔ)言,試圖使用正則表達(dá)式來(lái)凈化 HTML 幾乎總是失敗的。

你可能會(huì)找到建議你使用 strip_tags() 函數(shù)的觀點(diǎn)。 雖然 strip_tags() 從技術(shù)上來(lái)說(shuō)是安全的,但如果輸入的不合法的 HTML(比如, 沒有結(jié)束標(biāo)簽),它就成了一個(gè)「愚蠢」的函數(shù),可能會(huì)去除比你期望的更多的內(nèi)容。 由于非技術(shù)用戶在通信中經(jīng)常使用 < 和 > 字符,strip_tags() 也就不是一個(gè)好的選擇了。

如果閱讀了驗(yàn)證郵件地址一節(jié), 你也許也會(huì)考慮使用 filter_var() 函數(shù)。 然而 filter_var() 函數(shù)在遇到斷行時(shí)會(huì)出現(xiàn)問題, 并且需要不直觀的配置以接近 htmlentities() 函數(shù)的效果, 因此也不是一個(gè)好的選擇。

對(duì)于簡(jiǎn)單需求的凈化

如果你的 web 應(yīng)用僅需要完全地轉(zhuǎn)義(因此可以無(wú)害地呈現(xiàn),但不是完全去除) HTML, 則使用 PHP 的內(nèi)建 htmlentities() 函數(shù)。 這個(gè)函數(shù)要比 HTML Purifier 快得多,因此它不對(duì) HTML 做任何驗(yàn)證---僅轉(zhuǎn)義所有東西。

htmlentities() 不同于類似功能的函數(shù)htmlspecialchars(), 它會(huì)編碼所有適用的 HTML 實(shí)體,而不僅僅是一個(gè)小的子集。

示例

<?php
// Oh no!  The user has submitted malicious HTML, and we have to display it in our web app!
$evilHtml = '<div onclick="xss();">Mua-ha-ha!  Twiddling my evil mustache...</div>';

// Use the ENT_QUOTES flag to make sure both single and double quotes are escaped.
// Use the UTF-8 character encoding if you've stored the text as UTF-8 (as you should have).
// See the UTF-8 section in this document for more details.
$safeHtml = htmlentities($evilHtml, ENT_QUOTES, 'UTF-8');
// $safeHtml is now fully escaped HTML.  You can output $safeHtml to your users without fear!
?>

對(duì)于復(fù)雜需求的凈化

對(duì)于很多 web 應(yīng)用來(lái)說(shuō),簡(jiǎn)單地轉(zhuǎn)義 HTML 是不夠的。 你可能想完全去除任何HTML,或者允許一小部分子集的 HTML 存在。 若是如此,則使用 HTML Purifier 庫(kù)。

HTML Purifier 是一個(gè)經(jīng)過(guò)充分測(cè)試但效率比較低的庫(kù)。 這就是為什么如果你的需求并不復(fù)雜就應(yīng)使用 htmlentities(), 因?yàn)樗男室斓枚唷?/p>

HTML Purifier 相比 strip_tags() 是有優(yōu)勢(shì)的, 因?yàn)樗趦艋?HTML 之前會(huì)對(duì)其校驗(yàn)。 這意味著如果用戶輸入無(wú)效 HTML,HTML Purifier 相比 strip_tags() 更能保留 HTML 的原意。 HTML Purifier 高度可定制,允許你為 HTML 的一個(gè)子集建立白名單來(lái)允許這個(gè) HTML 子集的實(shí)體存在輸出中。

但其缺點(diǎn)就是相當(dāng)?shù)穆?,它要求一些設(shè)置,在一個(gè)共享主機(jī)的環(huán)境里可能是不可行的。 其文檔通常也復(fù)雜而不易理解。 以下示例是一個(gè)基本的使用配置。 查看文檔閱讀 HTML Purifier 提供的更多更高級(jí)的特性。

示例

<?php
// Include the HTML Purifier library
require_once('htmlpurifier-4.4.0/HTMLPurifier.auto.php');

// Oh no!  The user has submitted malicious HTML, and we have to display it in our web app!
$evilHtml = '<div onclick="xss();">Mua-ha-ha!  Twiddling my evil mustache...</div>';

// Set up the HTML Purifier object with the default configuration.
$purifier = new HTMLPurifier(HTMLPurifier_Config::createDefault());

$safeHtml = $purifier->purify($evilHtml);
// $safeHtml is now sanitized.  You can output $safeHtml to your users without fear!
?>

陷阱

  • 以錯(cuò)誤的字符編碼使用 htmlentities() 會(huì)造成意想不到的輸出。 在調(diào)用該函數(shù)時(shí)始終確認(rèn)指定了一種字符編碼,并且該編碼與將被凈化的字符串的編碼相匹配。 更多細(xì)節(jié)請(qǐng)查看 UTF-8 一節(jié)。

  • 使用 htmlentities() 時(shí),始終包含 ENT_QUOTES 和字符編碼參數(shù)。 默認(rèn)情況下,htmlentities() 不會(huì)對(duì)單引號(hào)編碼。多愚蠢的默認(rèn)做法!

  • HTML Purifier 對(duì)于復(fù)雜的 HTML 效率極其的低。可以考慮設(shè)置一個(gè)緩存方案如APC來(lái)保存經(jīng)過(guò)凈化的結(jié)果以備后用。

進(jìn)一步閱讀