一个诡异的 WordPress 登录用户验证问题

/wp-json/wp/v2/users 和 /wp-json/wp/v2/users/me 都需要登录验证后才能访问,/wp-json/wp/v2/users 正常,但是 /wp-json/wp/v2/users/me 不正常,User ID 为 0,但是通过以下代码又是能拿到 ID 的。

add_filter('rest_authentication_errors', function($result) {
    // 调试会话信息
    echo ('is_user_logged_in: ' . (is_user_logged_in() ? 'true' : 'false'));
    echo('Cookies: ' . print_r($_COOKIE, true));
    echo('Current User: ' . (wp_get_current_user()->ID ?: 'None'));

    if (!is_user_logged_in()) {
        return new WP_Error('rest_not_logged_in', 'You are not logged in.', ['status' => 401]);
    }

    $current_user_id = get_current_user_id();
    echo ('Current User ID: ' . $current_user_id);

    return $result;
});

解密,这里的 rest_cookie_check_errors 函数会在请求 REST 接口时验证 _wpnonce,如果没有提交这个字段,那么无法访问当前用户信息,而其他接口不需要访问 currrent_user。

#0 C:\www\test_006\wordpress\wp-includes\rest-api.php(1128): wp_set_current_user()
#1 C:\www\test_006\wordpress\wp-includes\class-wp-hook.php(324): rest_cookie_check_errors()
#2 C:\www\test_006\wordpress\wp-includes\plugin.php(205): apply_filters()
#3 C:\www\test_006\wordpress\wp-includes\rest-api\class-wp-rest-server.php(197): apply_filters()
#4 C:\www\test_006\wordpress\wp-includes\rest-api\class-wp-rest-server.php(436): check_authentication()
#5 C:\www\test_006\wordpress\wp-includes\rest-api.php(459): serve_request()
#6 C:\www\test_006\wordpress\wp-includes\class-wp-hook.php(324): rest_api_loaded()
#7 C:\www\test_006\wordpress\wp-includes\class-wp-hook.php(348): apply_filters()
#8 C:\www\test_006\wordpress\wp-includes\plugin.php(565): do_action()
#9 C:\www\test_006\wordpress\wp-includes\class-wp.php(418): do_action_ref_array()
#10 C:\www\test_006\wordpress\wp-includes\class-wp.php(818): parse_request()
#11 C:\www\test_006\wordpress\wp-includes\functions.php(1342): main()
#12 C:\www\test_006\wordpress\wp-blog-header.php(16): wp()
#13 C:\www\test_006\wordpress\index.php(17): require()
function rest_cookie_check_errors( $result ) {
    if ( ! empty( $result ) ) {
        return $result;
    }

    global $wp_rest_auth_cookie;

    /*
     * Is cookie authentication being used? (If we get an auth
     * error, but we're still logged in, another authentication
     * must have been used).
     */
    if ( true !== $wp_rest_auth_cookie && is_user_logged_in() ) {
        return $result;
    }

    // Determine if there is a nonce.
    $nonce = null;

    if ( isset( $_REQUEST['_wpnonce'] ) ) {
        $nonce = $_REQUEST['_wpnonce'];
    } elseif ( isset( $_SERVER['HTTP_X_WP_NONCE'] ) ) {
        $nonce = $_SERVER['HTTP_X_WP_NONCE'];
    }

    if ( null === $nonce ) {
        // No nonce at all, so act as if it's an unauthenticated request.
        wp_set_current_user( 0 );
        return true;
    }

    // Check the nonce.
    $result = wp_verify_nonce( $nonce, 'wp_rest' );

    if ( ! $result ) {
        add_filter( 'rest_send_nocache_headers', '__return_true', 20 );
        return new WP_Error( 'rest_cookie_invalid_nonce', __( 'Cookie check failed' ), array( 'status' => 403 ) );
    }

    // Send a refreshed nonce in header.
    rest_get_server()->send_header( 'X-WP-Nonce', wp_create_nonce( 'wp_rest' ) );

    return true;
}

最后解密,如果自己实现了 REST 验证,应该在 rest_authentication_errors 钩子回调中返回 true,来去除 rest_cookie_check_errors 调用。

add_filter( 'rest_authentication_errors', 'my_jwt_authentication_bypass', 5 );

function my_jwt_authentication_bypass( $result ) {
    // 如果已经有结果了(如错误),保持它
    if ( ! empty( $result ) ) {
        return $result;
    }

    // 检查 JWT(此处仅示意,你需根据自己的逻辑解析 token)
    $token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if ( str_starts_with( $token, 'Bearer ' ) ) {
        $jwt = substr( $token, 7 );
        $user_id = my_verify_jwt_and_get_user_id( $jwt ); // ← 你自己的解码逻辑

        if ( $user_id ) {
            wp_set_current_user( $user_id ); // 设置当前用户
            return true; // ✅ 验证成功,短路后续验证
        }
    }

    return null; // 继续后续验证
}

总结

  1. wordpress 的大多数服务端请求都带 determine_current_user 这个钩子验证,这个验证可以自定义验证用户是否登录,当然在自定义之前,用户已经判断过登录 cookie,已经从 cookie 中拿出 userid。 这里要做的是添加 jwt 验证。
  2. 即使 determine_current_user 做完,如果还想 jwt 认证来保护 wordpress 自带的接口,就需要定义 rest_authentication_errors 钩子回调,并在回调验证通过后返回 true,这样下一步的 NONCE 验证就不会启用。
  3. 不能简单的任务通过登录 cookie 验证过的登录用户就可以随意请求 REST 接口, wordpress 还有他自己的进一步验证机制,比如 NONCE 验证。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇