深入理解 WordPress `wp_get_current_commenter()` 函数的源码:如何从 `Cookie` 中获取评论者信息。

各位好,欢迎来到“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;
}

代码解读:一层一层剥开洋葱

  1. 静态变量的妙用static $commenter = null; 这一行,使用了静态变量。这意味着,这个函数只会执行一次从 Cookie 中获取信息的操作。以后再调用这个函数,直接返回之前的结果,省时省力。就像你第一次问路,记住路线后,下次就不用再问了。

  2. 默认值先行$commenter = array(...) 这部分,先设置了默认值,以防 Cookie 里啥也没有,也不至于返回空空如也。

  3. 登录用户优先if ( is_user_logged_in() ) 这部分,判断用户是否已经登录。如果登录了,直接从用户对象 $user 中获取信息,毕竟登录用户的身份是经过验证的,更可靠。

  4. 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。
  5. 过滤器加持$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} 评论者的网址

举个栗子

假设你的网站的 COOKIEHASHabcdef123456,你发表了一条评论,你的姓名是“张三”,邮箱是“[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 对用户体验和安全性的重视。

思考题

  1. 为什么 WordPress 要使用 Cookie 来存储评论者的信息?
  2. 除了 Cookie,还有哪些方法可以识别评论者的身份?
  3. 如何进一步提高 Cookie 的安全性?
  4. 如果禁用 Cookie,wp_get_current_commenter() 函数会如何工作?

总结陈词:小甜饼的大智慧

wp_get_current_commenter() 函数,就像一块小小的 Cookie,承载着 WordPress 对用户体验和安全性的思考。通过深入理解这个函数的源码,我们可以更好地理解 WordPress 的设计理念,并为自己的网站开发提供借鉴。希望今天的课程对大家有所帮助,下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注