WordPress 统一登录解决方案:奶狗Auth 授权登录插件
前言
你有没有遇到过这种场景:
自己有好几个网站——主站、资源站、工具站、文档站……每个站都要单独注册一套账号,用户记不住密码,你也管理不过来。
大厂是怎么解决的?QQ 互联、微信登录、GitHub 登录。用户点一下按钮,弹出授权页,点个"同意",就登录了。不用注册,不用记密码。
ngAuth 就是让你自己的 WordPress 站也能当"QQ"用的插件。
你的 WordPress 站作为账号中心(身份提供方),其他任何程序——不管是另一个 WordPress、PHP 网站还是 Node.js 项目——只要按标准 OAuth2 接口对接,就能实现"使用奶狗网账号登录"。
它能做什么
- 用户在你的授权页点一下"同意并授权",第三方站就能拿到这个用户的昵称、头像、唯一 ID
- 用户在第三方站不用注册,一个账号走遍你所有站点
- 授权页支持自定义应用图标、名称、描述,体验和大厂 OAuth 一致
- 已登录用户只需一次点击;未登录用户可在授权页内直接登录后继续授权
- 支持刷新 Token,授权长期有效;随时可吊销
技术特性
- 标准 OAuth2 授权码模式(Authorization Code),兼容现有各类 SDK 生态
- 提供 OpenID Discovery 元数据接口,标准客户端可自动发现接口地址
- 完整的 CORS 支持,前端跨域调用无障碍
- Access Token 2 小时有效,Refresh Token 30 天有效,支持吊销
- 授权码一次性使用,10 分钟过期,防重放
- 回调地址白名单前缀匹配,一个应用可绑定多个环境
- REST 前缀可自定义(默认 ngauth),避免与其他插件冲突
- 数据全部存在你自己的数据库里,不经过任何第三方
安装
- 将
ngauth目录上传到wp-content/plugins/ - 后台启用插件,数据表自动创建
- 进入"设置 - ngAuth 应用管理",新建一个应用:填写应用名称、图标、描述;回调地址白名单填第三方站的回调 URL(支持前缀匹配,一行一个);选择授权范围(basic / basic+email / profile)
- 保存后得到 App ID 和 App Secret,交给第三方开发者
授权流程
整个流程和 QQ 登录完全同构,共三步:
第一步,引导用户跳转到授权页:
https://你的域名/wp-json/ngauth/v1/authorize
?client_id=你的AppID
&redirect_uri=回调地址
&response_type=code
&scope=basic
&state=随机字符串
用户会看到一个精致的授权卡片:左边是第三方应用图标,右边是自己的头像,下方列出该应用将获得的权限,点"同意并授权"。
第二步,用户同意后,浏览器带着授权码跳回回调地址:
https://第三方站/callback?code=xxxxxxxx&state=随机字符串
第三方后端拿授权码换取访问令牌:
POST https://你的域名/wp-json/ngauth/v1/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=AppID
&client_secret=AppSecret
&code=第一步拿到的code
&redirect_uri=回调地址
返回:
{
"access_token": "at_xxx...",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "rt_xxx...",
"scope": "basic",
"openid": "uid_1_xxxx"
}
第三步,拿令牌获取用户资料:
GET https://你的域名/wp-json/ngauth/v1/userinfo
Authorization: Bearer at_xxx...
返回:
{
"openid": "uid_1_xxxx",
"site": "https://你的域名",
"app_id": "ngapp_xxx",
"username": "naigou",
"nickname": "奶狗",
"avatar": "https://.../avatar.png"
}
第三方站拿 openid 作为用户唯一标识:库里有这个 openid 就直接登录,没有就用昵称头像自动注册一个新账号。登录完成。
接口一览
| 接口 | 方法 | 说明 |
|---|---|---|
| /authorize | GET | 授权页,浏览器跳转 |
| /token | POST | 换取/刷新令牌 |
| /userinfo | GET/POST | 获取用户资料 |
| /revoke | POST | 吊销令牌 |
| /discovery | GET | OAuth2 元数据 |
所有接口 base 为 https://你的域名/wp-json/ngauth/v1,前缀可在后台修改。
刷新令牌
Access Token 2 小时过期后,无需让用户重新授权:
POST /token
grant_type=refresh_token
&client_id=AppID
&client_secret=AppSecret
&refresh_token=rt_xxx...
吊销令牌
用户解绑或应用下线时:
POST /revoke
client_id=AppID
&client_secret=AppSecret
&token=at_xxx...
对接示例(Node.js / Express)
const express = require('express');
const app = express();
const SSO = {
server: 'https://你的域名',
client_id: 'ngapp_xxx',
client_secret: 'ngsec_xxx',
redirect_uri: 'https://client.com/callback'
};
// 登录入口
app.get('/login', (req, res) => {
const state = Math.random().toString(36).slice(2);
req.session.state = state;
const url = `${SSO.server}/wp-json/ngauth/v1/authorize?` + new URLSearchParams({
client_id: SSO.client_id,
redirect_uri: SSO.redirect_uri,
response_type: 'code',
scope: 'basic',
state
});
res.redirect(url);
});
// 回调
app.get('/callback', async (req, res) => {
if (req.query.state !== req.session.state) return res.status(403).send('state 校验失败');
const tokenRes = await fetch(`${SSO.server}/wp-json/ngauth/v1/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: SSO.client_id,
client_secret: SSO.client_secret,
code: req.query.code,
redirect_uri: SSO.redirect_uri
})
}).then(r => r.json());
const user = await fetch(`${SSO.server}/wp-json/ngauth/v1/userinfo`, {
headers: { Authorization: `Bearer ${tokenRes.access_token}` }
}).then(r => r.json());
// 用 user.openid 查库,不存在则注册,存在则登录
req.session.user = user;
res.send(`欢迎你,${user.nickname}`);
});
安全设计
- 授权码一次性消费,用过即失效,10 分钟超时
- Token 采用 63 位加密随机串,数据库唯一索引校验
- client_secret 使用恒定时间比较,防时序攻击
- state 参数防 CSRF,授权页表单带 nonce 校验
- 回调地址严格白名单,前缀匹配在服务端完成
- refresh token 换新时旧 token 立即吊销(轮换机制)
常见问题
问:第三方站需要装 WordPress 吗?
不需要。ngAuth 服务端跑在你的 WordPress 上,客户端可以是任何语言任何框架,只要能发 HTTP 请求就行。
问:用户在第三方站改了密码会怎样?
不影响。第三方站只拿 openid 和基本资料,密码始终只存在你的主站。
问:怎么让用户解除授权?
用户主站个人中心可展示授权列表(调用 /revoke 吊销对应 token 即可),后台"最近 20 条授权记录"也能看到所有授权情况。
问:一个用户在多个应用登录,openid 一样吗?
一样。openid 绑定用户而不是应用,同一用户在所有应用处 openid 相同,方便你做全站统一账号。
下载
插件包:ngauth.zip,上传到 wp-content/plugins 后启用即可。配套的 test.html 可用于快速验证对接是否成功。
让用户一个账号走遍你所有的站,从此不再重复注册。这正是统一身份该有的样子。