各位好,欢迎来到“WordPress 源码解剖”小课堂。今天,我们要一起扒一扒 wp_get_current_commenter()
这个函数的老底,看看它是如何从神秘的 Cookie 宝箱里,掏出评论者的身份信息的。
开场白:谁是潜水者?
在茫茫人海的网络世界里,留言评论就像是丢进大海里的漂流瓶。我们怎么知道,是谁在偷偷地发表高见呢?WordPress 使用 Cookie 这种小甜饼,来记住那些曾经留下过足迹的评论者。wp_get_current_commenter()
函数,就像一位经验老道的寻宝者,专门负责从 Cookie 里挖出这些蛛丝马迹。
第一部分:wp_get_current_commenter()
函数的全貌
首先,让我们来看看 wp_get_current_commenter()
函数的庐山真面目:
function wp_get_current_commenter() {
static $commenter = null;
if ( null !== $commenter ) {
return $commenter;
}
$commenter = array(
'comment_author' => '',
'comment_author_email' => '',
'comment_author_url' => '',
);
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
$commenter['comment_author'] = $user->display_name;
$commenter['comment_author_email'] = $user->user_email;
$commenter['comment_author_url'] = $user->user_url;
} else {
$commenter['comment_author'] = ( isset( $_COOKIE['comment_author_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_' . COOKIEHASH] ) : '';
$commenter['comment_author_email'] = ( isset( $_COOKIE['comment_author_email_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_email_' . COOKIEHASH] ) : '';
$commenter['comment_author_url'] = ( isset( $_COOKIE['comment_author_url_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_url_' . COOKIEHASH] ) : '';
}
$commenter = apply_filters( 'wp_get_current_commenter', $commenter );
return $commenter;
}
代码解读:一层一层剥开洋葱
-
静态变量的妙用:
static $commenter = null;
这一行,使用了静态变量。这意味着,这个函数只会执行一次从 Cookie 中获取信息的操作。以后再调用这个函数,直接返回之前的结果,省时省力。就像你第一次问路,记住路线后,下次就不用再问了。 -
默认值先行:
$commenter = array(...)
这部分,先设置了默认值,以防 Cookie 里啥也没有,也不至于返回空空如也。 -
登录用户优先:
if ( is_user_logged_in() )
这部分,判断用户是否已经登录。如果登录了,直接从用户对象$user
中获取信息,毕竟登录用户的身份是经过验证的,更可靠。 -
Cookie 寻宝的关键:
else { ... }
这部分,是重头戏!如果用户未登录,就从 Cookie 里捞信息。关键在于这三行:$commenter['comment_author'] = ( isset( $_COOKIE['comment_author_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_' . COOKIEHASH] ) : ''; $commenter['comment_author_email'] = ( isset( $_COOKIE['comment_author_email_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_email_' . COOKIEHASH] ) : ''; $commenter['comment_author_url'] = ( isset( $_COOKIE['comment_author_url_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_url_' . COOKIEHASH] ) : '';
$_COOKIE
全局变量:$_COOKIE
是 PHP 的一个超级全局变量,它包含了所有客户端发送过来的 Cookie。isset()
函数:isset()
函数用来判断 Cookie 是否存在。- 三元运算符
?:
:这是一种简洁的if...else...
语句写法。如果 Cookie 存在,就获取它的值;否则,就使用空字符串作为默认值。 stripslashes()
函数:stripslashes()
函数用于移除反斜杠。这是因为,在将数据存入 Cookie 时,可能会自动添加反斜杠来转义特殊字符。取出来的时候,需要把这些反斜杠去掉,恢复数据的本来面目。COOKIEHASH
常量:COOKIEHASH
是一个随机字符串,用于增加 Cookie 的安全性。它可以防止恶意用户伪造 Cookie。
-
过滤器加持:
$commenter = apply_filters( 'wp_get_current_commenter', $commenter );
这一行,使用了 WordPress 的过滤器机制。允许其他插件或主题,修改$commenter
数组的内容。这就像给函数增加了一个“扩展口”,让它可以根据不同的需求进行定制。
第二部分:Cookie 的前世今生
要理解 wp_get_current_commenter()
函数,就必须先了解 Cookie 是如何产生的。当我们发表评论时,WordPress 会使用 setcookie()
函数,将评论者的信息存入 Cookie。
setcookie()
函数的用法
setcookie(
string $name,
string $value = "",
int $expires = 0,
string $path = "",
string $domain = "",
bool $secure = false,
bool $httponly = false
): bool
$name
:Cookie 的名称。例如,comment_author_your_cookie_hash
。$value
:Cookie 的值。例如,评论者的姓名。$expires
:Cookie 的过期时间。如果设置为 0,则 Cookie 会在浏览器关闭时过期。$path
:Cookie 的有效路径。通常设置为/
,表示对整个网站有效。$domain
:Cookie 的有效域名。$secure
:如果设置为 true,则 Cookie 只能通过 HTTPS 连接发送。$httponly
:如果设置为 true,则 Cookie 只能通过 HTTP 协议访问,不能通过 JavaScript 访问。这可以提高 Cookie 的安全性。
Cookie 的存储格式
WordPress 使用以下格式来存储评论者的信息:
Cookie 名称 | 描述 |
---|---|
comment_author_{COOKIEHASH} |
评论者的姓名 |
comment_author_email_{COOKIEHASH} |
评论者的邮箱 |
comment_author_url_{COOKIEHASH} |
评论者的网址 |
举个栗子
假设你的网站的 COOKIEHASH
是 abcdef123456
,你发表了一条评论,你的姓名是“张三”,邮箱是“[email protected]”,网址是“https://example.com”。那么,WordPress 会设置以下三个 Cookie:
comment_author_abcdef123456
=张三
comment_author_email_abcdef123456
=[email protected]
comment_author_url_abcdef123456
=https://example.com
第三部分:安全性考量
Cookie 存储评论者信息,虽然方便,但也存在一定的安全风险。恶意用户可能会伪造 Cookie,冒充他人发表评论。
WordPress 的安全措施
为了提高 Cookie 的安全性,WordPress 采取了以下措施:
COOKIEHASH
常量:使用随机字符串作为 Cookie 名称的一部分,增加 Cookie 的复杂性,防止恶意用户猜测 Cookie 名称。stripslashes()
函数:在从 Cookie 中获取数据时,使用stripslashes()
函数移除反斜杠,防止 XSS 攻击。- 过滤器机制:允许其他插件或主题,对 Cookie 进行验证和过滤,进一步提高安全性。
sanitize_email()
和esc_url_raw()
函数:在保存评论者的邮箱和网址时,使用sanitize_email()
和esc_url_raw()
函数,对数据进行过滤和转义,防止恶意代码注入。
安全建议
- 启用 HTTPS:使用 HTTPS 连接,可以加密 Cookie 的传输过程,防止 Cookie 被窃取。
- 设置
httponly
属性:将 Cookie 的httponly
属性设置为 true,可以防止 JavaScript 访问 Cookie,提高 Cookie 的安全性。 - 定期更换
COOKIEHASH
:定期更换COOKIEHASH
,可以使之前的 Cookie 失效,防止恶意用户利用过期的 Cookie。 - 使用验证码:在评论表单中添加验证码,可以防止机器人自动发表评论。
第四部分:实际应用
wp_get_current_commenter()
函数,在 WordPress 中被广泛使用。例如,在评论表单中,可以使用这个函数来预填充评论者的姓名、邮箱和网址。
示例代码
<?php
$commenter = wp_get_current_commenter();
$req = get_option( 'require_name_email' );
$aria_req = ( $req ? " aria-required='true'" : '' );
echo '<p class="comment-form-author">
<label for="author">' . __( 'Name', 'your-theme' ) . ( $req ? ' <span class="required">*</span>' : '' ) . '</label>
<input id="author" name="author" type="text" value="' . esc_attr( $commenter['comment_author'] ) . '" size="30"' . $aria_req . ' />
</p>';
echo '<p class="comment-form-email">
<label for="email">' . __( 'Email', 'your-theme' ) . ( $req ? ' <span class="required">*</span>' : '' ) . '</label>
<input id="email" name="email" type="text" value="' . esc_attr( $commenter['comment_author_email'] ) . '" size="30"' . $aria_req . ' />
</p>';
echo '<p class="comment-form-url">
<label for="url">' . __( 'Website', 'your-theme' ) . '</label>
<input id="url" name="url" type="text" value="' . esc_attr( $commenter['comment_author_url'] ) . '" size="30" />
</p>';
?>
代码解释
- 首先,使用
wp_get_current_commenter()
函数,获取评论者的信息。 - 然后,使用
esc_attr()
函数,对评论者的姓名、邮箱和网址进行转义,防止 XSS 攻击。 - 最后,将评论者的信息,填充到评论表单的相应字段中。
第五部分:深入思考
wp_get_current_commenter()
函数,虽然简单,但却蕴含着深刻的设计思想。它体现了 WordPress 对用户体验和安全性的重视。
思考题
- 为什么 WordPress 要使用 Cookie 来存储评论者的信息?
- 除了 Cookie,还有哪些方法可以识别评论者的身份?
- 如何进一步提高 Cookie 的安全性?
- 如果禁用 Cookie,
wp_get_current_commenter()
函数会如何工作?
总结陈词:小甜饼的大智慧
wp_get_current_commenter()
函数,就像一块小小的 Cookie,承载着 WordPress 对用户体验和安全性的思考。通过深入理解这个函数的源码,我们可以更好地理解 WordPress 的设计理念,并为自己的网站开发提供借鉴。希望今天的课程对大家有所帮助,下次再见!