You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress自定义插件实现OAuth2:实施思路与路由规划问询

WordPress 自定义 OAuth2 授权服务器实现方案

所需核心路由数量

根据OAuth2规范及你的需求,至少需要3个核心路由,对应授权服务器的标准端点:

  • 授权端点(Authorization Endpoint):处理用户授权请求,生成授权码
  • 令牌端点(Token Endpoint):用授权码/客户端凭证等换取访问令牌、刷新令牌
  • 用户信息端点(User Info Endpoint):通过有效访问令牌获取用户信息

如果需要支持客户端动态注册,可额外添加1个客户端注册路由,但自用场景下通常硬编码客户端信息即可,无需额外路由。

具体实施思路

1. 插件基础搭建与依赖引入

  • 创建自定义插件目录,通过Composer安装thephpleague/oauth2-server库,在插件主文件中引入Composer的autoload.php
  • 定义插件激活/停用钩子,确保依赖加载正常

2. 配置OAuth2服务器核心组件

需要实现以下核心存储类(对接WordPress数据库):

  • 客户端存储:存储客户端ID、密钥、重定向URI等信息(可自定义表或用选项存储)
  • 授权码存储:临时存储授权码,用于换取令牌
  • 令牌存储:存储访问令牌、刷新令牌及关联的用户ID
  • 用户认证提供者:对接WordPress的wp_authenticate函数,验证用户名密码的有效性

示例核心初始化代码:

use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Grant\AuthorizationCodeGrant;
use YourPlugin\Repositories\ClientRepository;
use YourPlugin\Repositories\AuthCodeRepository;
use YourPlugin\Repositories\AccessTokenRepository;
use YourPlugin\Repositories\RefreshTokenRepository;
use YourPlugin\Repositories\UserRepository;

function init_oauth_server() {
    $clientRepo = new ClientRepository();
    $authCodeRepo = new AuthCodeRepository();
    $accessTokenRepo = new AccessTokenRepository();
    $refreshTokenRepo = new RefreshTokenRepository();
    $userRepo = new UserRepository();

    // 加密密钥(从WordPress配置或插件选项获取)
    $privateKey = file_get_contents(plugin_dir_path(__FILE__) . 'private.key');
    $encryptionKey = 'your-encryption-key-here';

    $server = new AuthorizationServer(
        $clientRepo,
        $accessTokenRepo,
        $authCodeRepo,
        $privateKey,
        $encryptionKey
    );

    // 添加授权码授权模式(符合你的登录场景)
    $grant = new AuthorizationCodeGrant(
        $authCodeRepo,
        $refreshTokenRepo,
        new \DateInterval('PT10M') // 授权码有效期10分钟
    );
    $grant->setRefreshTokenTTL(new \DateInterval('P1M')); // 刷新令牌有效期1个月
    $server->enableGrantType($grant, new \DateInterval('PT1H')); // 访问令牌有效期1小时

    return $server;
}

3. 实现各核心路由

授权端点路由

处理用户授权请求,未登录用户需跳转到WordPress登录页,登录后可添加授权确认逻辑:

register_rest_route('oauth2/v1', '/authorize', [
    'methods' => ['GET', 'POST'],
    'callback' => 'handle_oauth_authorize',
    'permission_callback' => '__return_true', // 允许未登录用户访问,后续内部验证
]);

function handle_oauth_authorize(WP_REST_Request $request) {
    $server = init_oauth_server();
    $oauthRequest = \League\OAuth2\Server\RequestTypes\AuthorizationRequest::createFromGlobals();

    // 检查用户是否登录
    if (!is_user_logged_in()) {
        wp_redirect(wp_login_url(add_query_arg($_GET, rest_url('oauth2/v1/authorize'))));
        exit;
    }

    // 设置当前登录用户ID到授权请求
    $userEntity = new class(get_current_user_id()) implements \League\OAuth2\Server\Entities\UserEntityInterface {
        protected $identifier;
        public function __construct($id) { $this->identifier = $id; }
        public function getIdentifier() { return $this->identifier; }
    };
    $oauthRequest->setUser($userEntity);

    // 处理授权请求
    try {
        $response = $server->validateAuthorizationRequest($oauthRequest);
        // 此处可添加授权确认页面逻辑,比如让用户手动确认是否授权
        $response->setAuthorizationApproved(true); // 直接批准(或根据用户选择动态设置)
        $serverResponse = $server->completeAuthorizationRequest($response, new \Zend\Diactoros\Response());
    } catch (\Exception $e) {
        return new WP_REST_Response(['error' => $e->getMessage()], 400);
    }

    // 重定向到客户端重定向URI
    wp_redirect($serverResponse->getHeaderLine('Location'));
    exit;
}

令牌端点路由

处理授权码换取令牌的请求,同时支持刷新令牌逻辑:

register_rest_route('oauth2/v1', '/token', [
    'methods' => 'POST',
    'callback' => 'handle_oauth_token',
    'permission_callback' => '__return_true', // 客户端直接调用,无需WP登录
]);

function handle_oauth_token(WP_REST_Request $request) {
    $server = init_oauth_server();
    $oauthRequest = \Zend\Diactoros\ServerRequestFactory::fromGlobals();

    try {
        $response = $server->respondToAccessTokenRequest($oauthRequest, new \Zend\Diactoros\Response());
        return new WP_REST_Response(json_decode((string)$response->getBody(), true), $response->getStatusCode());
    } catch (\Exception $e) {
        return new WP_REST_Response(['error' => $e->getMessage()], 400);
    }
}

用户信息端点路由

通过有效访问令牌获取自定义的用户信息字段:

register_rest_route('oauth2/v1', '/userinfo', [
    'methods' => 'GET',
    'callback' => 'handle_oauth_userinfo',
    'permission_callback' => 'validate_oauth_token',
]);

function validate_oauth_token() {
    $server = init_oauth_server();
    $oauthRequest = \Zend\Diactoros\ServerRequestFactory::fromGlobals();

    try {
        $server->validateAuthenticatedRequest($oauthRequest);
        return true;
    } catch (\Exception $e) {
        return false;
    }
}

function handle_oauth_userinfo(WP_REST_Request $request) {
    // 获取令牌关联的用户ID(需在AccessTokenRepository中实现查询方法)
    $token = str_replace('Bearer ', '', $request->get_header('Authorization'));
    $userId = get_user_id_from_access_token($token);
    $user = get_user_by('id', $userId);

    // 返回自定义字段,可根据需求自由扩展
    return new WP_REST_Response([
        'id' => $user->ID,
        'username' => $user->user_login,
        'email' => $user->user_email,
        'display_name' => $user->display_name,
        // 添加你需要的自定义字段,比如用户角色、头像URL等
    ], 200);
}

4. 数据库表扩展

需要创建自定义表存储授权码、令牌、客户端信息,可在插件激活时执行SQL:

register_activation_hook(__FILE__, 'oauth2_plugin_activate');
function oauth2_plugin_activate() {
    global $wpdb;
    $charset_collate = $wpdb->get_charset_collate();

    // 创建客户端表
    $clients_table = $wpdb->prefix . 'oauth2_clients';
    $sql = "CREATE TABLE $clients_table (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        client_id varchar(255) NOT NULL,
        client_secret varchar(255) NOT NULL,
        redirect_uri text NOT NULL,
        grant_types varchar(255) DEFAULT 'authorization_code',
        PRIMARY KEY (id),
        UNIQUE KEY client_id (client_id)
    ) $charset_collate;";

    // 授权码表、令牌表的创建SQL类似,此处省略
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);

    // 插入测试客户端(可后续通过插件设置页面管理)
    $wpdb->insert($clients_table, [
        'client_id' => 'test-client',
        'client_secret' => 'test-secret',
        'redirect_uri' => 'https://your-client-app.com/callback'
    ]);
}

5. 测试与调试

  • 用Postman等工具测试各端点:
    1. 访问授权端点获取授权码
    2. 用授权码调用令牌端点获取访问令牌
    3. 用访问令牌调用用户信息端点获取自定义字段
  • 开启WordPress调试模式,排查路由或OAuth2库的错误

内容的提问来源于stack exchange,提问作者newbiedev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:05:32