wp_filter_oembed_result()
云策文档标注
概述
wp_filter_oembed_result() 是一个 WordPress 过滤器函数,用于过滤和清理 oEmbed HTML 结果,以增强安全性。它主要针对非受信任提供商的 'rich' 和 'video' 类型响应,通过限制允许的 HTML 标签和属性来防止恶意代码注入。
关键要点
- 函数用于过滤 oEmbed HTML,仅处理 'rich' 和 'video' 类型响应,其他类型直接返回原结果。
- 如果 URL 来自受信任的 oEmbed 提供商(通过 WP_oEmbed::get_provider() 检查),则不修改 HTML,直接返回。
- 对于非受信任提供商,使用 wp_kses() 严格限制允许的 HTML 标签和属性(如 a、blockquote、iframe 等)。
- 函数通过正则表达式提取 iframe 内容,并添加数据秘密(data-secret)以增强安全性。
- 返回过滤后的 HTML 字符串或 false(如果 iframe 不存在)。
代码示例
function wp_filter_oembed_result( $result, $data, $url ) {
if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) {
return $result;
}
$wp_oembed = _wp_oembed_get_object();
// Don't modify the HTML for trusted providers.
if ( false !== $wp_oembed->get_provider( $url, array( 'discover' => false ) ) ) {
return $result;
}
$allowed_html = array(
'a' => array(
'href' => true,
),
'blockquote' => array(),
'iframe' => array(
'src' => true,
'width' => true,
'height' => true,
'frameborder' => true,
'marginwidth' => true,
'marginheight' => true,
'scrolling' => true,
'title' => true,
),
);
$html = wp_kses( $result, $allowed_html );
preg_match( '|(.*?)?.*()|ms', $html, $content );
// We require at least the iframe to exist.
if ( empty( $content[2] ) ) {
return false;
}
$html = $content[1] . $content[2];
preg_match( '/ src=(['"])(.*?)1/', $html, $results );
if ( ! empty( $results ) ) {
$secret = wp_generate_password( 10, false );
$url = esc_url( "{$results[2]}#?secret=$secret" );
$q = $results[1];
$html = str_replace( $results[0], ' src=' . $q . $url . $q . ' data-secret=' . $q . $secret . $q, $html );
$html = str_replace( 'View all references View on Trac View on GitHub', '', $html );
}
return $html;
}注意事项
- 此函数在 WordPress 4.4.0 版本中引入,主要用于内部 oEmbed 处理,开发者通常不需要直接调用。
- 安全过滤依赖于 wp_kses() 和正则表达式,确保只允许预定义的 HTML 结构,避免 XSS 攻击。
- 如果 iframe 不存在于过滤后的 HTML 中,函数返回 false,可能导致嵌入失败。
- 相关函数包括 WP_oEmbed::get_provider()、wp_generate_password()、wp_kses()、_wp_oembed_get_object() 和 esc_url(),用于支持功能实现。
原文内容
Filters the given oEmbed HTML.
Description
If the $url isn’t on the trusted providers list, we need to filter the HTML heavily for security.
Only filters ‘rich’ and ‘video’ response types.
Parameters
$resultstring|falserequired-
The oEmbed HTML result.
$dataobjectrequired-
A data object result from an oEmbed provider.
$urlstringrequired-
The URL of the content to be embedded.
Source
function wp_filter_oembed_result( $result, $data, $url ) {
if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) {
return $result;
}
$wp_oembed = _wp_oembed_get_object();
// Don't modify the HTML for trusted providers.
if ( false !== $wp_oembed->get_provider( $url, array( 'discover' => false ) ) ) {
return $result;
}
$allowed_html = array(
'a' => array(
'href' => true,
),
'blockquote' => array(),
'iframe' => array(
'src' => true,
'width' => true,
'height' => true,
'frameborder' => true,
'marginwidth' => true,
'marginheight' => true,
'scrolling' => true,
'title' => true,
),
);
$html = wp_kses( $result, $allowed_html );
preg_match( '|(<blockquote>.*?</blockquote>)?.*(<iframe.*?></iframe>)|ms', $html, $content );
// We require at least the iframe to exist.
if ( empty( $content[2] ) ) {
return false;
}
$html = $content[1] . $content[2];
preg_match( '/ src=(['"])(.*?)1/', $html, $results );
if ( ! empty( $results ) ) {
$secret = wp_generate_password( 10, false );
$url = esc_url( "{$results[2]}#?secret=$secret" );
$q = $results[1];
$html = str_replace( $results[0], ' src=' . $q . $url . $q . ' data-secret=' . $q . $secret . $q, $html );
$html = str_replace( '<blockquote', "<blockquote data-secret="$secret"", $html );
}
$allowed_html['blockquote']['data-secret'] = true;
$allowed_html['iframe']['data-secret'] = true;
$html = wp_kses( $html, $allowed_html );
if ( ! empty( $content[1] ) ) {
// We have a blockquote to fall back on. Hide the iframe by default.
$html = str_replace( '<iframe', '<iframe style="position: absolute; visibility: hidden;"', $html );
$html = str_replace( '<blockquote', '<blockquote class="wp-embedded-content"', $html );
}
$html = str_ireplace( '<iframe', '<iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"', $html );
return $html;
}
Changelog
| Version | Description |
|---|---|
| 4.4.0 | Introduced. |