htmlentities() vs. htmlspecialchars():PHP 转义领域的巅峰对决
\n\n如果您曾经在网页上输出过用户数据,那么您一定听说过 htmlentities() 和 htmlspecialchars() 这两个函数。它们是 PHP 中防御 XSS 攻击并正确显示 HTML 字符的两个主要工具。但它们之间有什么区别?新手应该选择哪一个,专业人士又该选择哪一个?让我们一劳永逸地弄清楚。
想象一下:您正在用 PHP 编写一个博客,用户输入了一条评论:<script>alert('XSS')</script>。如果您直接将其输出到屏幕上,浏览器将执行该脚本。灾难!这时 htmlspecialchars() 和 htmlentities() 就派上用场了。但它们各自的工作方式不同。
htmlspecialchars() 和 htmlentities() 有什么共同点?
\n\n这两个函数都将特殊的 HTML 字符转换为其 HTML 实体。例如:
\n- \n
&(& 符号) →&\n <(小于号) →<\n >(大于号) →>\n "(双引号) →"\n '(单引号) →'(或根据标志位使用') \n
没有它们,任何包含尖括号或 & 符号的输入都会破坏页面布局,或为黑客打开大门。
\n\n主要区别:转换范围
\n\n这就是关键所在。htmlspecialchars() 是一个节俭的战士。它只转换在 HTML 中具有直接意义的五个主要字符:
- \n
&→&\n <→<\n >→>\n "→"\n '→'(如果启用了ENT_QUOTES标志位) \n
而 htmlentities() 则是一个完美主义者。它会转换所有存在对应 HTML 实体的字符。这不仅仅是尖括号,还包括货币符号 (€, £, ¥)、数学符号 (∑, ∂)、带变音符号的字母 (é, ñ, ü) 甚至表情符号 (☺)。
简单示例:实际中的区别
\n\n让我们看看代码。假设我们有一个包含法语的字符串:
\n\n<?php\n$text = "Café & thé <script>alert('test')</script>";\necho "htmlspecialchars: " . htmlspecialchars($text, ENT_QUOTES, 'UTF-8') . "<br>";\necho "htmlentities: " . htmlentities($text, ENT_QUOTES, 'UTF-8');\n?>\n\n结果:
\nhtmlspecialchars: Café & thé <script>alert('test')</script>\nhtmlentities: Café & thé <script>alert('test')</script>\n\n在这个例子中,没有区别,因为字符 "é" 和其他拉丁字母在 HTML 中没有特殊含义。但让我们尝试使用具有实体的字符:
\n\n<?php\n$text = "€ 100 <b>bold</b>";\necho "htmlspecialchars: " . htmlspecialchars($text, ENT_QUOTES, 'UTF-8') . "<br>";\necho "htmlentities: " . htmlentities($text, ENT_QUOTES, 'UTF-8');\n?>\n\n结果:
\nhtmlspecialchars: € 100 <b>bold</b>\nhtmlentities: € 100 <b>bold</b>\n\n看到了吗?htmlentities() 将欧元符号 "€" 转换为其实体 €。而 htmlspecialchars() 则保持原样。为什么?因为 "€" 对于 HTML 来说不是一个危险字符——即使不进行转义,浏览器也能正确显示它。
何时使用 htmlspecialchars()?
\n\n这是您的默认选择。在 99% 的情况下,当您输出用户数据时,请使用 htmlspecialchars()。