摸鱼派第三方登录(OAuth / OpenID)接入说明【新】
OAuth内容已完善,各位可以通过这个小脚本快速对接调试,为了更方便的管理和维护,请各位开发者及时同步更新。
当前版本:2026-06-22
1. 背景说明
摸鱼派提供一套类 OAuth / OpenID 的第三方登录能力。第三方站点可以引导用户跳转到摸鱼派完成登录与授权,随后通过服务端校验回跳参数,获取用户身份与已授权资源访问令牌。
当前版本支持:
- 使用摸鱼派账号登录第三方站点
- 按授权范围读取用户基础信息、积分信息、发帖信息
- 使用
access_token调用用户资源接口 - 使用
refresh_token无感续签access_token
2. 能力概览
第三方站点接入时,需要完成以下流程:
- 构造
/openid/login授权链接并跳转用户到摸鱼派。 - 用户确认授权后,摸鱼派回跳到第三方站点。
- 第三方站点调用
/openid/verify校验回跳参数。 - 校验通过后获得
access_token与refresh_token。 - 使用
Authorization: Bearer <access_token>调用用户资源接口。 access_token过期前后,可通过/openid/token使用refresh_token续签。
3. 授权范围
第三方站点可以在 /openid/login 中通过 fishpi.scope 请求需要的权限。多个权限可使用空格或英文逗号分隔。
| Scope | 说明 |
|---|---|
profile.read |
读取用户基础信息 |
points.read |
读取用户积分余额与积分记录 |
articles.read |
读取用户公开发帖记录 |
说明:
- 不传
fishpi.scope时,默认按profile.read处理。 - 第三方站点请求的权限会在授权页默认勾选且不可取消。
- 用户可以额外勾选站点未请求的权限。
- 如果最终授权范围缺少站点请求的权限,本次授权失败。
4. 接入流程
4.1 发起登录
GET /openid/login
第三方站点构造授权地址,并将用户浏览器跳转到该地址。
请求:
| Key | 必填 | 说明 | 示例 |
|---|---|---|---|
openid.ns |
是 | 固定为http://specs.openid.net/auth/2.0 |
http://specs.openid.net/auth/2.0 |
openid.mode |
是 | 固定为checkid_setup |
checkid_setup |
openid.return_to |
是 | 授权完成后的回调地址;生产环境应使用 HTTPS | https://example.com/callback |
openid.realm |
是 | 信任域范围,必须是openid.return_to 的前缀 |
https://example.com |
openid.identity |
是 | 固定为http://specs.openid.net/auth/2.0/identifier_select |
http://specs.openid.net/auth/2.0/identifier_select |
openid.claimed_id |
是 | 同openid.identity |
http://specs.openid.net/auth/2.0/identifier_select |
fishpi.scope |
否 | 授权范围,空格或逗号分隔 | profile.read points.read |
请求示例:
https://fishpi.cn/openid/login?openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.mode=checkid_setup&openid.return_to=https%3A%2F%2Fexample.com%2Fcallback&openid.realm=https%3A%2F%2Fexample.com&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&fishpi.scope=profile.read+points.read
注意:
- URL 参数需要按规范编码。
openid.realm必须是openid.return_to的前缀。- 生产环境回调地址建议使用 HTTPS;本地开发可使用
localhost或127.0.0.1。
4.2 接收授权回跳
用户确认授权后,摸鱼派会重定向到 openid.return_to,并在 URL 中携带 OpenID 参数。
常见回跳参数:
| Key | 说明 |
|---|---|
openid.ns |
协议声明 |
openid.mode |
固定为id_res |
openid.op_endpoint |
摸鱼派 OpenID 服务入口 |
openid.claimed_id |
用户唯一标识 URL |
openid.identity |
用户唯一标识 URL |
openid.return_to |
回调地址 |
openid.response_nonce |
一次性随机串 |
openid.assoc_handle |
关联信息 |
openid.signed |
参与签名的字段列表 |
openid.sig |
签名值 |
openid.claimed_id / openid.identity 末尾通常包含用户 oId,例如:
https://fishpi.cn/openid/id/1659430635383
回跳参数不能直接作为可信登录结果,必须先调用
/openid/verify校验。
4.3 校验回跳参数
POST /openid/verify
第三方站点服务端必须调用该接口校验回跳参数真实性。
请求:
| Key | 说明 |
|---|---|
Content-Type |
application/json |
| 请求体 | 回跳收到的openid.* 参数 |
openid.mode |
调用校验时改为check_authentication |
请求示例:
curl --location --request POST 'https://fishpi.cn/openid/verify' \
--header 'Content-Type: application/json' \
--data-raw '{
"openid.ns": "http://specs.openid.net/auth/2.0",
"openid.mode": "check_authentication",
"openid.op_endpoint": "https://fishpi.cn/openid",
"openid.claimed_id": "https://fishpi.cn/openid/id/1659430635383",
"openid.identity": "https://fishpi.cn/openid/id/1659430635383",
"openid.return_to": "https://example.com/callback",
"openid.response_nonce": "2026-06-22T00:00:00Zxxxxxxxxxx",
"openid.assoc_handle": "1234567890",
"openid.sig": "xxx"
}'
成功响应为纯文本:
ns:http://specs.openid.net/auth/2.0
is_valid:true
scope:profile.read points.read
token_type:Bearer
access_token:xxx
expires_in:604800
refresh_token:xxx
refresh_expires_in:31104000
失败响应为纯文本:
ns:http://specs.openid.net/auth/2.0
is_valid:false
响应字段:
| Key | 说明 | 示例 |
|---|---|---|
ns |
协议声明 | http://specs.openid.net/auth/2.0 |
is_valid |
校验是否通过 | true |
scope |
用户最终授权范围 | profile.read points.read |
token_type |
令牌类型 | Bearer |
access_token |
用户资源访问令牌 | xxx |
expires_in |
access_token 有效期,单位秒 |
604800 |
refresh_token |
续签令牌 | xxx |
refresh_expires_in |
refresh_token 空闲有效期,单位秒 |
31104000 |
安全要求:
openid.response_nonce是一次性参数,成功或失败校验后都不应重复使用。openid.response_nonce有效期为 5 分钟。access_token默认有效期为 7 天。refresh_token默认空闲有效期为 360 天,最长不超过首次授权后 720 天。refresh_token不应暴露到前端页面、浏览器存储、URL 或日志中。
4.4 续签访问令牌
POST /openid/token
使用 refresh_token 续签 access_token。该接口不使用登录态,不接收 apiKey。
请求:
| Key | 必填 | 说明 | 示例 |
|---|---|---|---|
grant_type |
是 | 固定为refresh_token |
refresh_token |
refresh_token |
是 | 当前有效的续签令牌 | xxx |
请求示例:
curl --location --request POST 'https://fishpi.cn/openid/token' \
--header 'Content-Type: application/json' \
--data-raw '{
"grant_type": "refresh_token",
"refresh_token": "xxx"
}'
成功响应:
{
"code": 0,
"msg": "",
"data": {
"token_type": "Bearer",
"access_token": "xxx",
"expires_in": 604800,
"refresh_token": "xxx",
"refresh_expires_in": 31104000,
"scope": "profile.read points.read"
}
}
失败响应:
{
"code": -1,
"msg": "无权限",
"data": {}
}
说明:
- 每次续签成功都会返回新的
refresh_token。 - 旧
refresh_token会立即失效。 - 如果已失效的旧
refresh_token被重复使用,同一授权链路下的有效续签令牌会被撤销。 - 续签不会扩大权限范围,新的
access_token沿用原授权范围。
5. 用户资源接口
用户资源接口统一使用:
Authorization: Bearer <access_token>
资源接口不接收 apiKey,不支持传 userId 代查其他用户。
5.1 查询用户基础信息
GET /openid/user/profile
需要授权范围:profile.read
请求示例:
curl --location --request GET 'https://fishpi.cn/openid/user/profile' \
--header 'Authorization: Bearer xxx'
响应字段:
| Key | 说明 | 示例 |
|---|---|---|
code |
0 为成功,-1 为失败 | 0 |
msg |
错误消息 | |
data.userId |
用户oId |
1659430635383 |
data.userName |
用户名 | admin |
data.userNickname |
昵称 | 管理员 |
data.userAvatarURL |
头像 | https://file.fishpi.cn/a.png |
5.2 查询用户积分记录
GET /openid/user/points
需要授权范围:points.read
请求参数:
| Key | 必填 | 说明 | 示例 |
|---|---|---|---|
p |
否 | 页码,默认1 |
1 |
size |
否 | 每页数量,默认20,最大 200 |
20 |
请求示例:
curl --location --request GET 'https://fishpi.cn/openid/user/points?p=1&size=20' \
--header 'Authorization: Bearer xxx'
响应字段:
| Key | 说明 |
|---|---|
data.userId |
用户oId |
data.userPoint |
当前积分 |
data.records |
积分记录列表 |
data.records[].oId |
记录oId |
data.records[].fromId |
支出用户oId |
data.records[].toId |
收入用户oId |
data.records[].sum |
积分数量 |
data.records[].type |
记录类型 |
data.records[].time |
记录时间 |
data.records[].dataId |
关联数据 |
data.records[].memo |
备注 |
data.records[].operation |
收支方向 |
data.records[].balance |
操作后余额 |
data.records[].displayType |
类型名称 |
data.records[].description |
记录描述 |
data.pagination |
分页信息 |
5.3 查询用户发帖记录
GET /openid/user/articles
需要授权范围:articles.read
请求参数:
| Key | 必填 | 说明 | 示例 |
|---|---|---|---|
p |
否 | 页码,默认1 |
1 |
size |
否 | 每页数量,默认20,最大 100 |
20 |
请求示例:
curl --location --request GET 'https://fishpi.cn/openid/user/articles?p=1&size=20' \
--header 'Authorization: Bearer xxx'
响应字段:
| Key | 说明 |
|---|---|
data.userId |
用户oId |
data.articles |
发帖记录列表 |
data.articles[].oId |
帖子oId |
data.articles[].articleTitle |
标题 |
data.articles[].articlePermalink |
链接 |
data.articles[].articleTags |
标签 |
data.articles[].articleCreateTime |
创建时间 |
data.articles[].articleUpdateTime |
更新时间 |
data.articles[].articleCommentCount |
回帖数 |
data.articles[].articleViewCount |
浏览数 |
data.articles[].articleType |
帖子类型 |
data.articles[].articlePerfect |
是否优选 |
data.pagination |
分页信息 |
说明:
- 仅返回公开、非匿名、未删除的发帖记录。
- 不返回正文、草稿、IP、UA 等敏感信息。
6. 错误处理
6.1 /openid/verify
/openid/verify 返回纯文本。只要 is_valid 不是 true,第三方站点都应视为登录失败。
常见原因:
openid.response_nonce已使用或过期openid.sig签名不匹配openid.return_to与openid.realm不匹配openid.mode没有改为check_authentication- 回跳参数不完整
6.2 /openid/token 与资源接口
JSON 接口通常返回:
{
"code": -1,
"msg": "无权限",
"data": {}
}
常见原因:
access_token缺失、伪造或过期refresh_token缺失、伪造、过期或已轮换- 当前 token 不包含目标资源所需授权范围
- 用户状态无效
7. 接入建议
- 第三方服务端保存
refresh_token,不要交给前端长期保存。 access_token可以按expires_in做本地过期判断。- 调用资源接口返回无权限时,可先尝试使用
refresh_token续签一次。 - 续签成功后必须替换本地保存的旧
refresh_token。 - 日志中应脱敏
access_token、refresh_token、openid.sig。 - 不要跳过
/openid/verify,也不要直接信任回跳 URL 中的用户 ID。
8. 流程总结
- 第三方站点跳转用户到
/openid/login。 - 用户在摸鱼派确认授权。
- 摸鱼派回跳到
openid.return_to。 - 第三方站点调用
/openid/verify。 is_valid:true后保存用户标识、授权范围和令牌。- 使用
access_token调用/openid/user/*。 - 使用
refresh_token调用/openid/token续签。
-
系统公告
105 引用
收到
太强辣!
感谢使用手册
tql辣
太强辣!
技术贴!
😋学习学习