转义输出是通过剥离不需要的数据(如格式错误的 HTML 或脚本标签)来保护输出数据的过程。此过程有助于在将数据呈现给最终用户之前确保数据安全。
转义函数
WordPress 提供了许多辅助函数,可用于大多数常见场景。
请仔细关注每个函数的作用,因为有些会移除 HTML,而有些则允许保留 HTML。您必须根据要输出的内容和上下文选择最合适的函数。始终应在 echo 时进行转义,而不是在此之前。
esc_html()– 在任何 HTML 元素包围要显示的数据部分时使用。这将移除 HTML。
<h4><?php echo esc_html( $title ); ?></h4>esc_js()– 用于内联 JavaScript。
<div onclick='<?php echo esc_js( $value ); ?>' />esc_url()– 用于所有 URL,包括 HTML 元素的 src 和 href 属性中的 URL。
<img alt="" src="<?php echo esc_url( $media_url ); ?>" />esc_url_raw()– 当在数据库中存储 URL 或在其他需要未编码 URL 的情况下使用。esc_xml()– 用于转义 XML 块。esc_attr()– 用于所有打印到 HTML 元素属性中的内容。
<ul class="<?php echo esc_attr( $stored_class ); ?>">esc_textarea()– 用于对 textarea 元素内的文本进行编码。wp_kses()– 用于安全地转义所有非受信任的 HTML(帖子文本、评论文本等)。这会保留 HTML。wp_kses_post()–wp_kses()的替代版本,自动允许帖子内容中允许的所有 HTML。wp_kses_data()–wp_kses()的替代版本,仅允许帖子评论中允许的 HTML。
自定义转义示例
如果您需要以特定方式转义输出,wp_kses()(发音为"kisses")函数将非常有用。
该函数确保您的输出中只会出现指定的 HTML 元素、属性和属性值,并规范化 HTML 实体。
<?php
echo wp_kses_post( $partial_html );
echo wp_kses(
$another_partial_html,
array(
'a' => array(
'href' => array(),
'title' => array(),
),
'br' => array(),
'em' => array(),
'strong' => array(),
)
); ?>在此示例中,除了 <a>、<br>、<em> 和 <strong> 之外的所有标签都将被移除。此外,如果传递了 <a> 标签,转义将确保只返回 href 和 title。
始终延迟转义
最好在尽可能晚的时候进行输出转义,理想情况下是在输出数据时进行。
延迟转义有几个好处:
- 代码审查和部署可以更快,因为可以一眼看出输出是否安全,而不必在许多行代码中查找是否已经进行了转义以及在哪里转义的。
- 变量可能在首次转换后到输出前被意外更改,从而引入潜在漏洞。
- 延迟转义使得自动代码扫描更容易,节省时间并减少审查和部署时间。
- 尽可能延迟转义可以使代码更健壮且面向未来。
- 在输出时进行转义/转换消除了任何歧义并增加了清晰度(始终为维护者开发)。
// 可以,但不够好。
$url = esc_url( $url );
$text = esc_html( $text );
echo '<a href="'. $url . '">' . $text . '</a>';
// 好得多!
echo '<a href="'. esc_url( $url ) . '">' . esc_html( $text ) . '</a>';… 除非无法延迟时
有时延迟转义并不实际。在极少数情况下,输出无法传递给 wp_kses(),因为根据定义,它会剥离正在生成的脚本。
在这种情况下,始终在创建字符串时进行转义,并将值存储在以 _escaped、_safe 或 _clean 作为后缀的变量中(例如,$variable 变为 $variable_escaped 或 $variable_safe)。
如果函数无法内部输出并延迟转义,则必须始终返回“安全”HTML。这使得可以直接执行 echo my_custom_script_code();,而无需通过允许此类标签的 wp_kses() 版本的脚本标签。
与本地化结合转义
与其使用 echo 输出数据,通常使用 WordPress 本地化函数,例如 _e() 或 __()。
这些函数只是在转义函数内包装一个本地化函数:
esc_html_e( 'Hello World', 'text_domain' );
// 等同于
echo esc_html( __( 'Hello World', 'text_domain' ) );这些辅助函数结合了本地化和转义:
示例
转义在任何地方使用的任意数值变量
echo $int;
根据它是整数还是浮点数,(int)、absint()、(float) 都是正确且可接受的。
有时,number_format() 或 number_format_i18n() 可能更合适。
intval()、floatval() 是可接受的,但是过时的(PHP4)函数。
转义 HTML 属性内的任意变量
echo '<div id="', $prefix, '-box', $id, '">';
这应该用一次 esc_attr() 调用进行转义。
当变量用作属性或 URL 的一部分时,最好转义整个字符串,这样变量前面潜在的转义字符将被正确转义。
正确:
echo '<div id="', esc_attr( $prefix . '-box' . $id ), '">';错误:
echo '<div id="', esc_attr( $prefix ), '-box', esc_attr( $id ), '">';
注意:使用 wp_create_nonce() 创建的 nonce 如果在 HTML 属性中使用,也应这样转义。
在 HTML 属性中转义任意 URL,但也适用于其他上下文
echo '<a href="', $url, '">';
这应该使用 esc_url() 进行转义。
正确:
echo '<a href="', esc_url( $url ), '">';错误:
echo '<a href="', esc_attr( $url ), '">'; echo '<a href="', esc_attr( esc_url( $url ) ), '">';
通过 wp_localize_script() 将任意变量传递给 JavaScript
wp_localize_script( 'handle', 'name',
array(
'prefix_nonce' => wp_create_nonce( 'plugin-name' ),
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'errorMsg' => __( 'An error occurred', 'plugin-name' ),
)
);无需转义,WordPress 会自动转义。
转义 JavaScript 块内的任意变量
<script type="text/javascript">
var myVar = <?php echo $my_var; ?>
</script>$my_var 应使用 esc_js() 进行转义。
正确:
<script type="text/javascript">
var myVar = <?php echo esc_js( $my_var ); ?>
</script>转义内联 JavaScript 内的任意变量
<a href="#" onclick="do_something(<?php echo $var; ?>); return false;">
$var 应使用 esc_js() 进行转义。
正确:
<a href="#" onclick="do_something(<?php echo esc_js( $var ); ?>); return false;">转义供 JavaScript 使用的 HTML 属性内的任意变量
<a href="#" data-json="<?php echo $var; ?>">
$var 应使用 esc_js()、json_encode() 或 wp_json_encode() 进行转义。
正确:
<a href="#" data-json="<?php echo esc_js( $var ); ?>">转义 HTML textarea 内的任意字符串
echo '<textarea>', $data, '</textarea>';
$data 应使用 esc_textarea() 进行转义。
正确:
echo '<textarea>', esc_textarea( $data ), '</textarea>';转义 HTML 标签内的任意字符串
echo '<div>', $phrase, '</div>';
这取决于$phrase是否预期包含 HTML。
- 如果不包含,请使用
esc_html()或其任何变体。 - 如果预期包含 HTML,请使用
wp_kses_post()、wp_kses_allowed_html()或wp_kses()并指定您想要允许的 HTML 标签集合。
转义 XML 或 XSL 上下文中的任意字符串
echo '<loc>', $var, '</loc>';
使用esc_xml()或ent2ncr()进行转义。
正确做法:
echo '<loc>', ent2ncr( $var ), '</loc>';