
你的 WordPress 博客只有原生注册登录,用户需要单独注册一个账号,流失率高、体验差。如果能用 GitCode 账号一键登录,注册门槛直接归零。
昨天我给自己的博客 blog.rmzdb.cloud 开发了一个 GitCode OAuth 2.0 登录插件,从设计 OAuth 流程到写 PHP 代码再到接入 AeroCore 主题,半天时间搞定。这篇文章把整个过程完整记录下来,涉及 OAuth 2.0 协议、WordPress 插件开发、前端 DOM 注入和 Token 生命周期管理,全程可复现。
GitCode 是 CSDN 旗下的国内头部代码托管平台,开发者群体和我的博客受众高度重合。"用 GitCode 登录"比"用 Google 登录"对国内开发者友好得多,而且 OAuth 2.0 接口完全标准化,和 GitHub / Gitee 的对接模式一模一样。
另外,GitCode OAuth 的 Token 交换接口接受 client_secret 放在 POST body,和 GitHub 行为一致,比 Gitee 的 Basic Auth Header 方式更简洁。
整个登录过程分为 4 步:
用户点击「GitCode登录」→ 跳转 GitCode 授权页 → 用户授权 → 回调博客 → 换 Token → 拉用户信息 → 匹配/创建 WP 账号 → 登录
用户点击按钮后,WordPress 收到 ?action=gitcode_login 请求,插件构造授权 URL 并 302 跳转:
$params = [
'client_id' => 'your_client_id',
'redirect_uri' => home_url('/wp-login.php?action=gitcode_callback'),
'response_type' => 'code',
'scope' => 'all_user',
'state' => wp_generate_password(32, false), // 防 CSRF
];
wp_redirect('https://gitcode.com/oauth/authorize?' . http_build_query($params));
exit;关键细节:
response_type=code 指定使用授权码模式(Authorization Code Grant),这是唯一正确的选择scope=all_user 请求用户基本信息权限// 校验 state
$state = $_GET['state'] ?? '';
if (empty($state) || !get_transient('gcol_state_' . $state)) {
wp_die('State 校验失败,可能是 CSRF 攻击,请重新登录。');
}
delete_transient('gcol_state_' . $state);
// 用 code 换 token
$url = 'https://gitcode.com/oauth/token?' . http_build_query([
'grant_type' => 'authorization_code',
'code' => $code,
'client_id' => $client_id,
]);
$response = wp_remote_post($url, [
'body' => ['client_secret' => $client_secret],
'timeout' => 15,
]);注意 client_secret 放在 POST body 而不是 URL 参数里——这是 GitCode 的安全设计,和 GitHub 一致。
$response = wp_remote_get('https://api.gitcode.com/api/v5/user', [
'headers' => ['Authorization' => 'Bearer ' . $access_token],
'timeout' => 15,
]);
$gitcode_user = json_decode(wp_remote_retrieve_body($response), true);拿到 id、username、email、name、avatar_url 等字段。
这是整个插件最核心的逻辑——三策略用户匹配:
// 策略1: 按 gitcode_id meta 精确匹配(已绑定过)
$users = get_users([
'meta_key' => 'gcol_gitcode_id',
'meta_value' => $gitcode_user['id'],
'number' => 1,
]);
// 策略2: 按邮箱匹配(GitCode 邮箱 = WP 邮箱)
if ($gitcode_user['email']) {
$user = get_user_by('email', $gitcode_user['email']);
}
// 策略3: 自动注册新账号
$user_id = wp_insert_user([
'user_login' => $username,
'user_email' => $email,
'display_name' => $display_name,
'user_pass' => wp_generate_password(24),
'role' => $cfg['default_role'] ?: 'subscriber',
]);三策略覆盖了所有场景:老用户回访(策略1)、已有 WP 账号绑 GitCode(策略2)、纯新用户(策略3),登录体验无缝衔接。
整个插件 3 个 PHP 文件,职责分明:
plugins/gitcode-oauth-login/
├── gitcode-oauth-login.php # 入口:单例 + 配置集中管理
├── includes/
│ ├── class-settings.php # 后台设置页面
│ ├── class-oauth.php # OAuth 核心流程 + 前端注入
│ └── class-profile.php # 用户资料页绑定展示final class GCOL_Plugin
{
private static $instance = null;
public static function instance()
{
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct()
{
GCOL_Settings::init();
GCOL_OAuth::init();
GCOL_Profile::init();
}
public static function config($key = null)
{
return [
'client_id' => get_option('gcol_client_id', ''),
'client_secret' => get_option('gcol_client_secret', ''),
'auto_register' => get_option('gcol_auto_register', '1'),
'default_role' => get_option('gcol_default_role', 'subscriber'),
];
}
}
GCOL_Plugin::instance();单例确保整个请求生命周期只有一个插件实例,不污染全局空间。配置通过 get_option 持久化到 wp_options 表。
用 register_setting + add_settings_section + add_settings_field 构建后台设置页:
public static function field_callback()
{
$url = home_url('/wp-login.php?action=gitcode_callback');
echo '<input type="text" readonly value="' . esc_attr($url) . '" onclick="this.select()" />';
}用 login_form 钩子往原生登录页注入 GitCode 按钮:
add_action('login_form', [__CLASS__, 'login_button']);
public static function login_button()
{
$url = wp_login_url() . '?action=gitcode_login';
echo '<div class="gitcode-login-divider">—— 或 ——</div>';
echo '<a href="' . esc_url($url) . '" class="gitcode-login-btn">GitCode 账号登录</a>';
}标准做法是只往 wp-login.php 加按钮就够了。但 AeroCore 主题把登录入口放在了头部导航栏,通过 #login-trigger 元素 + 弹窗实现——没有走 WordPress 原生登录页。
要在这旁边放 GitCode 按钮,就得用 JavaScript 在 wp_footer 动态注入:
add_action('wp_footer', [__CLASS__, 'inject_frontend_button']);
public static function inject_frontend_button()
{
if (is_user_logged_in()) return;
$login_url = esc_url(wp_login_url() . '?action=gitcode_login');
?>
<script>
(function(){
var btn = document.createElement('a');
btn.href = '<?php echo $login_url; ?>';
btn.title = 'GitCode 账号登录';
function tryInject() {
var target = document.getElementById('login-trigger');
if (!target) target = document.querySelector('.header-actions .user-avatar-placeholder');
if (!target) target = document.querySelector('a[href*="wp-login.php"]');
if (target && target.parentNode) {
target.parentNode.insertBefore(btn, target.nextSibling);
}
}
// 多重试机制,应对异步渲染
setTimeout(tryInject, 500);
setTimeout(tryInject, 2000);
setTimeout(tryInject, 5000);
})();
</script>
<?php
}这里用了多重试注入策略:500ms、2s、5s 各尝试一次。因为现代主题很多是 Vue / React 渲染的,DOM 就绪时机不固定。三次尝试覆盖了绝大多数场景。
按钮样式:32×32 黑色圆角方块,内嵌珊瑚红 G 字 SVG Logo,和深色主题风格完美融合。
用
已登录:站长 | 退出
短码把登录按钮放在文章、页面、侧边栏任意位置:
add_shortcode('gitcode_login', [__CLASS__, 'shortcode_button']);
public static function shortcode_button()
{
if (is_user_logged_in()) {
return '已登录:' . esc_html(wp_get_current_user()->display_name);
}
$url = wp_login_url() . '?action=gitcode_login';
return '<a href="' . esc_url($url) . '">GitCode 账号登录</a>';
}GitCode Access Token 有效期有限,但提供了 refresh_token(有效期 15 天)。插件在每次成功登录时持久化:
update_user_meta($user_id, 'gcol_access_token', $token['access_token']);
update_user_meta($user_id, 'gcol_refresh_token', $token['refresh_token']);
update_user_meta($user_id, 'gcol_avatar_url', $gitcode_user['avatar_url']);
update_user_meta($user_id, 'gcol_profile_url', $gitcode_user['html_url']);并提供刷新方法供外部调用:
public static function refresh_token($user_id)
{
$url = 'https://gitcode.com/oauth/token?' . http_build_query([
'grant_type' => 'refresh_token',
'refresh_token' => get_user_meta($user_id, 'gcol_refresh_token', true),
]);
$response = wp_remote_post($url, ['timeout' => 15]);
// ... 更新 access_token 和 refresh_token
}开发过程中刻意做了安全左移,把安全问题解决在设计阶段:
措施 | 说明 |
|---|---|
State 参数 | 随机 32 位字符串,transients 存储 5 分钟,回调强制校验,防 CSRF |
client_secret 保护 | 存 options 表,设置页用 password 类型遮罩,不暴露在前端 |
回调地址锁定 | 必须在 GitCode 应用配置中精确匹配,防止授权码被劫持 |
输入过滤 | 所有来自 GitCode 的返回数据都用 sanitize_* 系列函数过滤 |
输出转义 | 所有 HTML 输出都用 esc_html / esc_url / esc_attr 转义 |
auto_register 开关 | 管理员可按需关闭,防止未授权用户自动注册 |
https://你的博客/wp-login.php?action=gitcode_callback已登录:站长 | 退出短码GitCode OAuth 只是一个起点。同样的架构(Settings / OAuth / Profile 三组件分离)可以快速扩展到其他平台:
一个下午写出来的 GitCode OAuth 登录插件,代码量不大(3 个文件不到 300 行),但覆盖了 OAuth 2.0 完整流程、WordPress 后台设置标准 API、前端 DOM 注入兼容、短码支持和 Token 管理。
核心经验:
完整代码已开源在 GitCode:gitcode.com/zqwlkeji/gitcode-oauth-login,欢迎 Star、Fork、提 Issue,直接拿去用或魔改。