早上好,各位观众老爷!今天咱们来聊聊 WordPress 里一个非常重要的函数——wp_kses()
。这玩意儿就像个保安,专门负责过滤用户输入,防止恶意代码溜进你的网站。但保安总不能啥都拦着吧?所以 WordPress 提供了 _wp_kses_allowed_html
钩子,让咱们可以自定义白名单,告诉保安哪些 HTML 标签和属性是“良民”,可以放行。
咱们今天就来扒一扒 wp_kses()
的源码,看看它是怎么利用这个钩子来实现自定义白名单的。准备好了吗?发车!
wp_kses()
:一个 HTML 标签和属性的“洁癖症患者”
首先,我们来认识一下 wp_kses()
这个函数。它的主要作用就是过滤 HTML 标签和属性,只允许白名单上的标签和属性通过,其他的统统咔嚓掉。
简单来说,wp_kses()
就像一个非常严格的 HTML 验证器,它会根据你定义的规则(白名单)来判断哪些 HTML 代码可以保留,哪些需要删除。
_wp_kses_allowed_html
钩子:给保安送“通行证”
_wp_kses_allowed_html
钩子就相当于你给保安送了一份“通行证”名单,告诉他名单上的人(HTML 标签和属性)是你的朋友,可以自由出入。
这个钩子允许开发者修改 wp_kses()
默认的 HTML 白名单。你可以添加新的标签和属性,也可以删除已有的标签和属性,从而定制符合你网站需求的过滤规则。
源码剖析:wp_kses()
是如何工作的?
咱们直接上代码,看看 wp_kses()
的真面目:
function wp_kses( $string, $allowed_html, $allowed_protocols = array() ) {
// ... (一些初始化和参数处理) ...
$string = wp_kses_no_null( $string );
$string = wp_kses_normalize_entities( $string );
$string = wp_kses_hook( $string, $allowed_html, $allowed_protocols );
return $string;
}
可以看到,wp_kses()
函数主要做了以下几件事:
- 初始化和参数处理: 对输入字符串进行一些预处理,比如去除空字符。
- 规范化 HTML 实体: 将 HTML 实体转换为对应的字符。
- 调用
wp_kses_hook()
进行核心过滤: 这是最关键的一步,wp_kses_hook()
才是真正执行 HTML 过滤的函数。
咱们重点关注 wp_kses_hook()
这个函数,因为它内部使用了 _wp_kses_allowed_html
钩子。
function wp_kses_hook( $string, $allowed_html, $allowed_protocols ) {
// ... (一些变量定义和初始化) ...
/**
* Filters the list of allowed tags and attributes when using wp_kses().
*
* @since 2.0.0
*
* @param array $allowed_html An array of allowed HTML tags and their allowed attributes.
* @param string $string The HTML string being filtered.
* @param string $allowed_protocols An array of allowed protocols.
*/
$allowed_html = apply_filters( '_wp_kses_allowed_html', $allowed_html, $string, $allowed_protocols );
// ... (后续的 HTML 解析和过滤) ...
return $string;
}
看到了吗?在 wp_kses_hook()
函数中,有一行非常关键的代码:
$allowed_html = apply_filters( '_wp_kses_allowed_html', $allowed_html, $string, $allowed_protocols );
这行代码使用了 apply_filters()
函数来调用 _wp_kses_allowed_html
钩子。也就是说,在进行 HTML 过滤之前,wp_kses_hook()
会先询问所有注册了 _wp_kses_allowed_html
钩子的函数,让它们有机会修改 $allowed_html
数组。
$allowed_html
数组的结构:HTML 白名单的“户口本”
$allowed_html
数组是 wp_kses()
用来存储 HTML 白名单的数据结构。它的结构如下:
$allowed_html = array(
'tag_name' => array(
'attribute_name' => true,
'attribute_name' => true,
// ...
),
'another_tag_name' => array(
'attribute_name' => true,
// ...
),
// ...
);
其中:
tag_name
是 HTML 标签的名称,比如p
、a
、img
等。attribute_name
是 HTML 属性的名称,比如href
、src
、class
等。true
表示该属性是允许的。
举个例子,如果 $allowed_html
数组包含以下内容:
$allowed_html = array(
'p' => array(
'class' => true,
),
'a' => array(
'href' => true,
'title' => true,
),
);
那么 wp_kses()
就会允许以下 HTML 代码:
<p class="my-class">This is a paragraph.</p>
<a href="https://example.com" title="Example">Example Link</a>
但是会拒绝以下 HTML 代码:
<p style="color: red;">This is a paragraph.</p> <!-- style 属性被拒绝 -->
<a onclick="alert('Hello!');">Example Link</a> <!-- onclick 属性被拒绝 -->
自定义白名单:给保安“升级”通行证
现在,咱们来看看如何使用 _wp_kses_allowed_html
钩子来自定义白名单。
假设我们想允许 img
标签的 data-src
属性,就可以在 functions.php
文件中添加以下代码:
function my_custom_kses_allowed_html( $allowed_html, $string, $allowed_protocols ) {
$allowed_html['img']['data-src'] = true;
return $allowed_html;
}
add_filter( '_wp_kses_allowed_html', 'my_custom_kses_allowed_html', 10, 3 );
这段代码做了以下几件事:
- 定义一个函数
my_custom_kses_allowed_html()
: 这个函数接收三个参数:$allowed_html
:当前的 HTML 白名单数组。$string
:要过滤的 HTML 字符串。$allowed_protocols
:允许的协议数组(比如http
、https
等)。
- 修改
$allowed_html
数组: 在函数内部,我们修改$allowed_html
数组,将img
标签的data-src
属性设置为true
,表示允许该属性。 - 返回修改后的
$allowed_html
数组: 函数必须返回修改后的$allowed_html
数组,这样wp_kses()
才能使用新的白名单进行过滤。 -
使用
add_filter()
函数注册钩子:add_filter( '_wp_kses_allowed_html', 'my_custom_kses_allowed_html', 10, 3 );
这行代码将my_custom_kses_allowed_html()
函数注册到_wp_kses_allowed_html
钩子上。'_wp_kses_allowed_html'
是钩子的名称。'my_custom_kses_allowed_html'
是要执行的函数名称。10
是优先级,数字越小优先级越高。3
是传递给函数的参数个数。
这样,wp_kses()
在过滤 HTML 代码时,就会允许 img
标签的 data-src
属性。
更复杂的例子:允许自定义标签和属性
假设我们需要允许自定义标签 <my-tag>
和自定义属性 my-attribute
。可以这样做:
function my_custom_kses_allowed_html( $allowed_html, $string, $allowed_protocols ) {
$allowed_html['my-tag'] = array(
'my-attribute' => true,
);
return $allowed_html;
}
add_filter( '_wp_kses_allowed_html', 'my_custom_kses_allowed_html', 10, 3 );
这段代码会将 <my-tag my-attribute="value">
加入到白名单中。
需要注意的点:安全第一!
虽然 _wp_kses_allowed_html
钩子非常强大,可以让你自定义 HTML 白名单,但是在使用时一定要小心谨慎,避免引入安全漏洞。
- 只允许必要的标签和属性: 不要随意添加标签和属性,只允许那些确实需要的。
- 对属性值进行验证:
wp_kses()
只会检查属性是否存在于白名单中,不会验证属性值的安全性。因此,如果允许用户输入属性值,一定要进行额外的验证,防止 XSS 攻击。 - 使用
wp_kses_post()
或wp_kses_data()
: WordPress 提供了wp_kses_post()
和wp_kses_data()
函数,它们分别针对文章内容和普通数据进行了优化,使用了更安全的默认白名单。如果你的目的是过滤文章内容或普通数据,建议使用这两个函数。
wp_kses_post()
和 wp_kses_data()
:更专业的保安
wp_kses_post()
和 wp_kses_data()
函数都是对 wp_kses()
的封装,它们使用了不同的默认白名单,适用于不同的场景。
wp_kses_post()
: 用于过滤文章内容。它允许的标签和属性更多,更适合用于处理用户提交的富文本内容。wp_kses_data()
: 用于过滤普通数据。它允许的标签和属性更少,更安全,适合用于处理用户提交的普通文本数据。
在使用 wp_kses_post()
和 wp_kses_data()
时,也可以使用 _wp_kses_allowed_html
钩子来修改它们的默认白名单。
总结:wp_kses()
+ _wp_kses_allowed_html
= 灵活安全的 HTML 过滤
wp_kses()
函数是 WordPress 中用于过滤 HTML 代码的重要工具。_wp_kses_allowed_html
钩子则为开发者提供了自定义白名单的强大能力。
通过使用 _wp_kses_allowed_html
钩子,你可以根据自己的需求,定制 wp_kses()
的过滤规则,既保证了网站的安全性,又满足了用户的个性化需求。
表格总结
函数/钩子 | 作用 |
---|---|
wp_kses() |
过滤 HTML 标签和属性,只允许白名单上的标签和属性通过。 |
_wp_kses_allowed_html |
允许开发者修改 wp_kses() 默认的 HTML 白名单。 |
$allowed_html |
存储 HTML 白名单的数据结构,是一个关联数组,键是标签名,值是允许的属性数组。 |
wp_kses_post() |
用于过滤文章内容,使用了更适合富文本内容的默认白名单。 |
wp_kses_data() |
用于过滤普通数据,使用了更安全的默认白名单。 |
代码示例总结
-
允许
img
标签的data-src
属性:function my_custom_kses_allowed_html( $allowed_html, $string, $allowed_protocols ) { $allowed_html['img']['data-src'] = true; return $allowed_html; } add_filter( '_wp_kses_allowed_html', 'my_custom_kses_allowed_html', 10, 3 );
-
允许自定义标签
<my-tag>
和自定义属性my-attribute
:function my_custom_kses_allowed_html( $allowed_html, $string, $allowed_protocols ) { $allowed_html['my-tag'] = array( 'my-attribute' => true, ); return $allowed_html; } add_filter( '_wp_kses_allowed_html', 'my_custom_kses_allowed_html', 10, 3 );
安全提示总结
- 只允许必要的标签和属性。
- 对属性值进行验证,防止 XSS 攻击。
- 使用
wp_kses_post()
或wp_kses_data()
,它们使用了更安全的默认白名单。
好了,今天的讲座就到这里。希望大家对 wp_kses()
和 _wp_kses_allowed_html
钩子有了更深入的了解。记住,安全第一,合理使用,才能让你的 WordPress 网站更加安全可靠!感谢大家的观看,下次再见!