数据转义是确保输出安全的关键过程,通过移除恶意代码或格式错误的HTML来保护数据。WordPress提供了一系列转义函数,适用于不同场景,开发者需根据内容和上下文选择合适的函数,并遵循“尽可能晚转义”的原则。
// 转义HTML内容
<h4><?php echo esc_html( $title ); ?></h4>
// 转义URL
<img alt="" src="<?php echo esc_url( $media_url ); ?>" />
// 使用wp_kses()自定义转义
echo wp_kses(
$another_partial_html,
array(
'a' => array(
'href' => array(),
'title' => array(),
),
'br' => array(),
'em' => array(),
'strong' => array(),
)
);Escaping output is the process of securing output data by stripping out unwanted data, like malformed HTML or script tags. This process helps secure your data prior to rendering it for the end user.
WordPress has many helper functions you can use for most common scenarios.
Pay close attention to what each function does, as some will remove HTML while others will permit it. You must use the most appropriate function to the content and context of what you’re echoing. You always want to escape when you echo, not before.
esc_html() – Use anytime an HTML element encloses a section of data being displayed. This will remove HTML.<h4><?php echo esc_html( $title ); ?></h4>
esc_js() – Use for inline Javascript.<div onclick='<?php echo esc_js( $value ); ?>' />
esc_url() – Use on all URLs, including those in the src and href attributes of an HTML element.<img alt="" src="<?php echo esc_url( $media_url ); ?>" />
esc_url_raw() – Use when storing a URL in the database or in other cases where non-encoded URLs are needed.esc_xml() – Use to escape XML block.esc_attr() – Use on everything else that’s printed into an HTML element’s attribute.<ul class="<?php echo esc_attr( $stored_class ); ?>">
esc_textarea() – Use this to encode text for use inside a textarea element.wp_kses() – Use to safely escape for all non-trusted HTML (post text, comment text, etc.). This preserves HTML.wp_kses_post() – Alternative version of wp_kses()that automatically allows all HTML that is permitted in post content.wp_kses_data() – Alternative version of wp_kses()that allows only the HTML permitted in post comments.In the case that you need to escape your output in a specific way, the function wp_kses() (pronounced “kisses”) will come in handy.
This function makes sure that only the specified HTML elements, attributes, and attribute values will occur in your output, and normalizes HTML entities.
<?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(),
)
); ?>
In this example, all tags other than <a>, <br>, <em>, and <strong> will be stripped out. Additionally, if an <a> tag is passed, the escaping ensures that only the href and the title are returned.
It is best to do the output escaping as late as possible, ideally as data is being outputted.
It is better to escape late for a few reasons:
// Okay, but not great.
$url = esc_url( $url );
$text = esc_html( $text );
echo '<a href="'. $url . '">' . $text . '</a>';
// Much better!
echo '<a href="'. esc_url( $url ) . '">' . esc_html( $text ) . '</a>';
It is sometimes not practical to escape late. In a few rare circumstances output cannot be passed to wp_kses(), since by definition it would strip the scripts that are being generated.
In situations like this, always escape while creating the string and store the value in a variable that is a postfixed with _escaped, _safe or _clean (e.g., $variable becomes $variable_escaped or $variable_safe).
If a function cannot output internally and escape late, then it must always return “safe” HTML. This allows echo my_custom_script_code(); to be done without needing the script tag to be passed through a version of wp_kses() that would allow such tags.
Rather than using echo to output data, it’s common to use the WordPress localization functions, such as _e() or __().
These functions simply wrap a localization function inside an escaping function:
esc_html_e( 'Hello World', 'text_domain' );
// Same as
echo esc_html( __( 'Hello World', 'text_domain' ) );
These helper functions combine localization and escaping:
echo $int;
Depending on whether it is an integer or a float, (int), absint(), (float) are all correct and acceptable.
At times, number_format() or number_format_i18n() might be more appropriate.
intval(), floatval() are acceptable, but are outdated (PHP4) functions.
echo '<div id="', $prefix, '-box', $id, '">';
This should be escaped with one call to esc_attr().
When a variable is used as part of an attribute or url, it is always better to escape the whole string as that way a potential escape character just before the variable will be correctly escaped.
Correct:
echo '<div id="', esc_attr( $prefix . '-box' . $id ), '">';
Incorrect:
echo '<div id="', esc_attr( $prefix ), '-box', esc_attr( $id ), '">';
Note: nonces created using wp_create_nonce() should also be escaped like this if used in an HTML attribute.
echo '<a href="', $url, '">';
This should be escaped with esc_url().
Correct:
echo '<a href="', esc_url( $url ), '">';
Incorrect:
echo '<a href="', esc_attr( $url ), '">'; echo '<a href="', esc_attr( esc_url( $url ) ), '">';
wp_localize_script()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' ),
)
);
No escaping needed, WordPress will escape this.
<script type="text/javascript">
var myVar = <?php echo $my_var; ?>
</script>
$my_var should be escaped with esc_js().
Correct:
<script type="text/javascript"></script>
<a href="#" onclick="do_something(<?php echo $var; ?>); return false;">
$var should be escaped with esc_js().
Correct:
<a href="#" onclick="do_something(<?php echo esc_js( $var ); ?>); return false;">
<a href="#" data-json="<?php echo $var; ?>">
$var should be escaped with esc_js(), json_encode() or wp_json_encode().
Correct:
<a href="#" data-json="<?php echo esc_js( $var ); ?>">
echo '<textarea>', $data, '</textarea>';
$data should be escaped with esc_textarea().
Correct:
echo '<textarea>', esc_textarea( $data ), '</textarea>';
echo '<div>', $phrase, '</div>';
This depends on whether $phrase is expected to contain HTML or not.
esc_html() or any of its variants.wp_kses_post(), wp_kses_allowed_html() or wp_kses() with a set of HTML tags you want to allow.echo '<loc>', $var, '</loc>';
Escape with esc_xml() or ent2ncr().
Correct:
echo '<loc>', ent2ncr( $var ), '</loc>';