咳咳,麦克风测试,1, 2, 3… 各位观众老爷们,晚上好!我是你们的老朋友,今天咱们来聊聊 WordPress 里一个神奇的函数:wp_get_current_user()
。
你肯定用过它,对不对? 只要你想知道当前是谁在登录,或者获取登录用户的相关信息,那它就是你的不二之选。 可是,你有没有好奇过,它是怎么知道“现在是谁”的? 它背后到底藏着什么秘密?
今天,咱们就来扒一扒它的源码,看看它到底是怎么“指认”当前用户的。 准备好了吗? Let’s dive in!
1. 故事的开端:请求与用户
在 Web 世界里,每次用户访问网站,都是一次请求。 WordPress 要识别用户,必须在这些请求中找到用户的“身份证明”。 这个身份证明通常就是 Cookie。
Cookie 就像一张小纸条,浏览器会帮我们保管着。 当用户登录 WordPress 时,服务器会在用户的浏览器里种下几个 Cookie,记录用户的身份信息。 以后用户每次访问网站,浏览器都会自动把这些 Cookie 捎带上,这样服务器就能认出用户了。
2. wp_get_current_user()
函数的真面目
好了,有了这个基础,咱们来看看 wp_get_current_user()
到底做了什么。 打开 wp-includes/pluggable.php
文件,找到这个函数,你会发现它其实很简单:
function wp_get_current_user() {
global $current_user;
if ( ! ( $current_user instanceof WP_User ) ) {
$current_user = wp_get_current_user_info();
}
return $current_user;
}
是不是感觉有点意外? 这么常用的函数,代码竟然这么短! 它主要做了两件事:
- 检查
$current_user
全局变量:$current_user
是一个全局变量,用来存储当前用户的WP_User
对象。 函数首先检查这个变量是否已经存在,并且是否是WP_User
的实例。 - 如果
$current_user
不存在或不是WP_User
实例: 调用wp_get_current_user_info()
函数来获取用户信息,并赋值给$current_user
。
所以,真正的秘密都在 wp_get_current_user_info()
函数里。 咱们接着往下看。
3. wp_get_current_user_info()
: 抽丝剥茧
wp_get_current_user_info()
函数的代码稍微长一点,但也别怕,咱们一步一步来:
function wp_get_current_user_info() {
static $cache = array();
$user = null;
if ( defined( 'XMLRPC_REQUEST' ) || defined( 'REST_REQUEST' ) || ( defined( 'WP_INSTALLING' ) && WP_INSTALLING ) || is_admin() ) {
if ( isset( $_REQUEST['user_id'] ) && is_numeric( $_REQUEST['user_id'] ) ) {
$user_id = (int) $_REQUEST['user_id'];
$user = get_userdata( $user_id );
}
// Grant access to any XMLRPC request
// Grant access to REST requests that have authentication handled.
// Grant access during install.
// Grant access if a user is set in admin.
}
if ( empty( $user ) ) {
/** This filter is documented in wp-includes/pluggable.php */
$user_id = apply_filters( 'determine_current_user', false );
if ( $user_id ) {
$user = get_userdata( $user_id );
}
}
if ( empty( $user ) ) {
$user = wp_validate_auth_cookie();
}
if ( empty( $user ) ) {
$user = new WP_User( 0 );
}
/**
* Filters the current user's data.
*
* @since 2.1.0
*
* @param WP_User $user WP_User object for the current user.
*/
$user = apply_filters( 'wp_get_current_user', $user );
return $user;
}
看起来有点复杂,咱们把它拆解成几个部分:
-
特殊情况处理: 函数首先检查一些特殊情况,比如是否是 XMLRPC 请求、REST 请求、安装过程或者在后台管理界面。 如果是这些情况,它可能会尝试从
$_REQUEST['user_id']
获取用户 ID,然后用get_userdata()
函数获取用户信息。 这些情况通常用于程序内部调用,或者是一些特殊的 API 请求。 -
determine_current_user
过滤器: 这是一个非常重要的过滤器。 开发者可以通过这个过滤器自定义用户识别逻辑。 例如,你可以根据自己的 Cookie 格式或者其他方式来确定用户 ID,然后返回。 -
wp_validate_auth_cookie()
: 这是最核心的部分! 如果前面的方法都失败了,函数会调用wp_validate_auth_cookie()
函数来验证用户的认证 Cookie。 这个函数会检查 Cookie 的有效性,并从中提取用户 ID。 -
默认用户: 如果所有方法都失败了,说明用户没有登录。 函数会创建一个
WP_User
对象,并将用户 ID 设置为 0,表示匿名用户。 -
wp_get_current_user
过滤器: 这是最后一个过滤器,允许开发者对最终的WP_User
对象进行修改。
4. wp_validate_auth_cookie()
: 验证身份的关键
咱们重点来看看 wp_validate_auth_cookie()
函数,因为它才是真正负责验证用户身份的关键。 这个函数的代码比较长,咱们只看关键部分:
function wp_validate_auth_cookie( $cookie = '', $scheme = '' ) {
if ( ! $cookie ) {
if ( isset( $_COOKIE[LOGGED_IN_COOKIE] ) ) {
$cookie = $_COOKIE[LOGGED_IN_COOKIE];
} else {
return false;
}
}
$cookie_elements = explode( '|', $cookie );
if ( count( $cookie_elements ) !== 4 ) {
return false;
}
list( $username, $expiration, $token, $hmac ) = $cookie_elements;
$user = get_user_by( 'login', $username );
if ( ! $user ) {
return false;
}
$pass_frag = substr( $user->user_pass, 8, 4 );
$key = wp_hash( $username . '|' . $pass_frag . '|' . $expiration . '|' . $token, 'logged_in' );
$hash = hash_hmac( 'md5', $username . '|' . $expiration . '|' . $token, $key );
if ( hash_equals( $hmac, $hash ) ) {
return $user;
}
return false;
}
这个函数主要做了以下几件事:
-
获取 Cookie: 首先,它尝试从
$_COOKIE[LOGGED_IN_COOKIE]
中获取用户的认证 Cookie。LOGGED_IN_COOKIE
是一个常量,定义了 Cookie 的名称,通常是wordpress_logged_in_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
。 -
解析 Cookie: Cookie 的值是一个字符串,用
|
分隔成四个部分:用户名、过期时间、Token 和 HMAC。 -
获取用户: 根据用户名,使用
get_user_by( 'login', $username )
函数获取WP_User
对象。 -
验证 HMAC: HMAC (Hash-based Message Authentication Code) 是一种消息认证码,用于验证 Cookie 的完整性和真实性。 函数会根据用户名、密码片段、过期时间和 Token,重新计算 HMAC,然后与 Cookie 中的 HMAC 进行比较。 如果两者一致,说明 Cookie 是有效的,没有被篡改。
-
返回用户: 如果 Cookie 验证通过,函数会返回
WP_User
对象。 否则,返回false
。
5. 总结: wp_get_current_user()
的工作流程
现在,咱们可以总结一下 wp_get_current_user()
函数的工作流程了:
- 检查
$current_user
全局变量。 - 如果
$current_user
不存在或不是WP_User
实例,则调用wp_get_current_user_info()
。 wp_get_current_user_info()
函数:- 处理特殊情况(XMLRPC、REST、安装、后台)。
- 应用
determine_current_user
过滤器。 - 调用
wp_validate_auth_cookie()
验证认证 Cookie。 - 如果所有方法都失败,则创建匿名用户。
- 应用
wp_get_current_user
过滤器。
- 返回
$current_user
。
用表格来总结一下:
函数 | 功能 |
---|---|
wp_get_current_user() |
获取当前登录用户的 WP_User 对象。 优先使用全局变量 $current_user ,如果不存在则调用 wp_get_current_user_info() 获取。 |
wp_get_current_user_info() |
确定当前用户的信息。 依次尝试以下方法:处理特殊情况,应用 determine_current_user 过滤器,调用 wp_validate_auth_cookie() ,创建匿名用户。 最后应用 wp_get_current_user 过滤器。 |
wp_validate_auth_cookie() |
验证用户的认证 Cookie。 从 Cookie 中提取用户名、过期时间、Token 和 HMAC,然后验证 HMAC 的有效性。 如果验证通过,则返回 WP_User 对象。 |
6. 深入思考:安全性与扩展性
通过分析源码,我们可以发现 wp_get_current_user()
函数的设计考虑了安全性与扩展性。
-
安全性:
wp_validate_auth_cookie()
函数使用 HMAC 来验证 Cookie 的完整性和真实性,防止 Cookie 被篡改。 同时,密码片段的使用也增加了破解 Cookie 的难度。 -
扩展性:
determine_current_user
和wp_get_current_user
过滤器允许开发者自定义用户识别逻辑和修改用户信息,提供了很大的灵活性。 例如,你可以使用第三方认证系统,或者根据用户的角色来动态修改用户权限。
7. 举个栗子:自定义用户识别逻辑
假设你想要根据一个名为 MY_CUSTOM_COOKIE
的 Cookie 来识别用户。 你可以使用 determine_current_user
过滤器来实现:
add_filter( 'determine_current_user', 'my_custom_determine_current_user' );
function my_custom_determine_current_user( $user_id ) {
if ( ! empty( $_COOKIE['MY_CUSTOM_COOKIE'] ) ) {
$custom_user_id = $_COOKIE['MY_CUSTOM_COOKIE'];
if ( is_numeric( $custom_user_id ) ) {
return (int) $custom_user_id;
}
}
return $user_id;
}
这段代码会检查是否存在 MY_CUSTOM_COOKIE
,如果存在,并且它的值是一个数字,则将其作为用户 ID 返回。 这样,wp_get_current_user()
函数就会根据你的自定义逻辑来识别用户了。
8. 总结与展望
今天,咱们一起深入了解了 wp_get_current_user()
函数的源码,揭开了它“指认”当前用户的秘密。 从 Cookie 的验证,到过滤器的应用,再到安全性与扩展性的考虑,这个函数的设计体现了 WordPress 的精髓。
希望今天的讲座能够帮助你更好地理解 WordPress 的用户认证机制,并在实际开发中更加灵活地使用 wp_get_current_user()
函数。
记住,代码的世界充满了乐趣,只要你敢于探索,就能发现更多的惊喜! 下次有机会,咱们再一起聊聊 WordPress 的其他有趣的函数。
感谢大家的聆听,咱们下期再见! (鞠躬)