在 Web 開發中,直接將用戶提交的數據輸出到頁面是極其危險的。惡意用戶可能在輸入中嵌入 JavaScript 代碼,例如:
<script language="javascript">alert('Do something bad!');</script>
若未經過濾直接輸出,這段腳本將在受害者瀏覽器中執行,導致跨站腳本攻擊(XSS)。即使非惡意輸入,未閉合的 HTML 標籤也可能破壞頁面結構,導致排版錯亂或內容截斷。
使用 htmlspecialchars() 將所有特殊字符轉換為 HTML 實體編碼:
$safe_output = htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
這樣 <b> 會變為 <b>,徹底消除 HTML 注入風險。但缺點是用戶無法使用任何格式化功能。
參考 BBCode 風格,提供安全的標記供用戶使用:
[b]粗體[/b] → <strong>粗體</strong>[i]斜體[/i] → <em>斜體</em>[link="url"]連結[/link] → <a href="url">連結</a>[quote]引用[/quote] → <blockquote>引用</blockquote><?php
function format_output($output) {
// 1. 先完全轉義,徹底禁用原始 HTML
$output = htmlspecialchars(stripslashes($output), ENT_QUOTES, 'UTF-8');
// 2. 再轉換自定義標記為安全 HTML
$output = str_replace('[b]', '<strong>', $output);
$output = str_replace('[/b]', '</strong>', $output);
$output = str_replace('[i]', '<em>', $output);
$output = str_replace('[/i]', '</em>', $output);
// 處理連結(需防範 javascript: 協議)
$output = str_replace('[link="javascript', '[link=" javascript', $output);
$output = preg_replace('/\[link="([^"]+)"\]/', '<a href="$1">', $output);
$output = str_replace('[/link]', '</a>', $output);
// 3. 最後處理換行
return nl2br($output);
}
?>
htmlspecialchars() 再替換自定義標記,否則自定義標記產生的 HTML 會被再次轉義javascript: 協議,防止通過連結注入腳本",正則需匹配實體編碼後的字符nl2br() 必須在最後調用這種「白名單」機制既保證了安全性,又賦予用戶基本排版能力,是處理用戶生成內容(UGC)的經典最佳實踐。