外观
鉴权机制
Notanote API 的所有第三方接口均要求同时提供两种鉴权凭证,缺一不可:
- 应用身份凭证(TID + SecretKey):证明调用来自你的应用
- 用户授权凭证(name + access_token):证明玩家已同意授权
鉴权凭证概览
| 凭证 | 内容 | 证明什么 | 是否必须 |
|---|---|---|---|
| 应用身份凭证 | TID + SecretKey | 你是哪个应用 | 是 |
| 用户授权凭证 | name + access_token | 玩家同意授权 | 是 |
应用身份凭证(TID + SecretKey)
使用方式
在所有第三方接口的请求体中传入 tid 和 secretkey:
json
{
"tid": 1001,
"secretkey": "your-secret-key"
}Notanote 服务端会校验 tid + secretkey 是否匹配你的应用记录。不匹配则返回 TIDVerifyFailed。
SecretKey 保管
SecretKey 等同于你的应用密码,只能在服务端使用,禁止写入客户端代码或前端配置。泄露后攻击者可以冒充你的应用发起任意请求,包括拉取玩家存档、伪造授权流程。
用户授权凭证(WebAuth)
WebAuth 是 Notanote 提供给第三方应用的 OAuth 风格网页授权机制。你的应用通过 WebAuth 可以获取玩家授权的 access_token,进而读取该玩家的存档数据。
整体流程
mermaid
sequenceDiagram
participant App as 你的服务端
participant Nano as Notanote API
participant User as 玩家浏览器
App->>Nano: ① POST /webauth/get-session
Nano-->>App: 返回 auth-session(5 分钟有效)
App->>User: ② 302 重定向到 Notanote 授权页
User->>Nano: ③ 玩家登录并确认授权
Nano->>Nano: 校验身份 → 生成 access_token → 作废 auth-session
Nano-->>User: ④ 返回 redirect_url
User->>App: ⑤ 浏览器跳转到 callback(携带 access_token + state)
App->>App: ⑥ 校验 state,存储 access_token步骤说明
步骤一:获取临时会话
你的服务端用 tid + secretkey 向 Notanote 换取 auth-session,同时传入:
state:你生成的随机字符串,用于 CSRF 防护callback:授权完成后的回跳地址
具体接口见下方 获取临时会话。
步骤二:引导玩家授权
将玩家浏览器重定向到 Notanote 授权页面,URL 中携带 auth-session:
https://nano.notanote.cn/authorize?auth-session={你的 auth-session}步骤三:玩家确认授权
授权页通过 auth-session 查询你的应用信息(名称、作者、授权范围),展示给玩家确认。玩家在授权页输入 Notanote 账号密码后:
- Notanote 校验玩家身份
- 生成
access_token - 作废
auth-session(一次性使用,无法重放) - 返回
redirect_url给前端
步骤四:浏览器跳转
前端执行跳转,浏览器访问你的 callback 地址,授权参数通过 URL query 传递:
| 参数 | 说明 |
|---|---|
name | 玩家的 Notanote 用户名 |
access_token | 第三方授权令牌 |
state | 你在步骤一传入的 state,原样回传 |
步骤五:校验 state
你的 callback 页面收到请求后,必须校验 state 与步骤一发出的一致,通过后再存储 access_token。
js
// 伪代码
if (receivedState !== yourOriginalState) {
// state 不匹配,拒绝本次回调,可能是 CSRF 攻击
return res.status(403).send('state 校验失败');
}
// 校验通过,安全地存储 access_token关键设计
- 服务端不主动请求 callback:Notanote 返回
redirect_url由浏览器跳转完成回调。既避免 SSRF 风险,也避免服务端到第三方服务端之间的网络故障影响授权流程。 - state 由你全权管理:
state由你生成并传入,Notanote 原样存入、原样回传,不解析 state 内容。生成与校验完全由你负责。
展示模式(callback="show")
将 callback 设为字符串 "show" 即启用展示模式,专为 QQ 机器人等无法提供回调地址的接入场景 设计。与 URL 回调模式的差异从授权完成那一刻开始:浏览器不跳转,而是在授权页直接展示一个授权码,由玩家复制后手动交给第三方接入者。
授权码格式
展示模式下页面展示给玩家的是一个完整的授权码字符串,格式为:
{name}.{token}| 组成部分 | 含义 |
|---|---|
name | 玩家的 Notanote 用户名 |
. | 固定分隔符 |
token | 第三方授权令牌(access_token) |
例如玩家 player1 授权成功后,页面展示的授权码形如 player1.a1b2c3d4e5f6。
第三方接入者收到授权码后,以第一个 . 为界拆分:前半部分作为 Name,后半部分作为 Token,即可调用后续第三方接口(如存档读取):
js
// 解析展示模式授权码
const dot = code.indexOf(".");
const name = code.slice(0, dot); // 玩家用户名
const token = code.slice(dot + 1); // access_token流程
mermaid
sequenceDiagram
participant App as 你的服务端
participant Nano as Notanote API
participant User as 玩家浏览器
participant 3rd as 第三方接入者
App->>Nano: ① POST /webauth/get-session(callback="show")
Nano-->>App: 返回 auth-session
App->>User: ② 302 重定向到 Notanote 授权页
User->>Nano: ③ 玩家登录并确认授权
Nano->>Nano: 生成 access_token,作废 auth-session
Nano-->>User: ④ 页面直接展示授权码(name.token)
User->>3rd: ⑤ 玩家复制授权码,手动发送给第三方接入者
3rd->>3rd: ⑥ 按第一个 "." 拆分,得到 name 与 access_token
3rd->>Nano: ⑦ 用 name + access_token 调用第三方接口与 URL 回调模式的区别
| 对比维度 | URL 回调模式 | 展示模式(callback="show") |
|---|---|---|
| 回调方式 | 浏览器自动跳转到你的回调 URL | 页面直接展示授权码,不跳转 |
| 是否需托管 | 需要公网可访问的回调地址 | 不需要任何回调地址 |
| 适用场景 | Web 应用、有服务端的场景 | QQ 机器人、无法托管回调地址的场景 |
| state 校验 | 在回调路由中校验 | 由你的服务端在处理后续调用时酌情校验 |
| 凭证传递 | name 与 access_token 走 URL query | 授权码 {name}.{token} 由玩家手动复制 |
展示模式设计意图
展示模式专为解决 QQ 机器人等无法提供回调地址的接入场景 而设计。玩家在 Notanote 授权页完成授权后,页面直接展示授权码({name}.{token}),玩家复制后发送给第三方接入者(如 QQ 群内机器人客服),第三方拆分出 name 与 token 即可调用后续接口。
获取临时会话 POST /webauth/get-session
获取临时授权会话。由你的服务端调用,禁止在前端直接调用。
接口地址:POST https://api.notanote.cn/webauth/get-session
请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
tid | number | 是 | 你的第三方应用 ID |
secretkey | string | 是 | 你的第三方应用密钥 |
scope | string | 是 | 授权范围,目前仅支持 access_token |
callback | string | 是 | 授权完成后的回跳地址(合法 URL),或填入 "show" 启用展示模式 |
state | string | 是 | 你生成的随机字符串,用于 CSRF 防护,建议至少 16 字符 |
请求示例
json
{ // 下面是 form-data 转化成 json 的形式
"tid": 1001,
"secretkey": "{your-secret-key}",
"scope": "access_token",
"callback": "{https://your-app.com/oauth/callback}",
"state": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6...(随机的 16~32 bytes 字符串)"
}成功响应
json
{
"Status": true,
"Response": {
"Identifier": "nano.api.v2.webauth.get-session.succeed",
"Data": {
"auth-session": "AbC123...XYz789",
"expire_in": 300
}
}
}| 字段 | 类型 | 说明 |
|---|---|---|
auth-session | string | 临时会话令牌,用于构造授权页 URL |
expire_in | number | 有效期(秒),固定为 300(5 分钟) |
callback 由你传入
callback 由你在请求时传入,合法值包括:
- HTTPS URL:授权完成后浏览器自动跳转到该地址
"show":授权完成后在页面直接展示授权码({name}.{token}),适用于 QQ 机器人等无法托管回调地址的场景
你必须确保 secretkey 不泄露,否则攻击者可伪造 callback 劫持授权结果。
失败响应
| Identifier | 说明 | 处理建议 |
|---|---|---|
nano.api.v2.webauth.get-session.failed.TIDVerifyFailed | tid 或 secretkey 错误 | 检查凭证是否正确、应用是否被禁用 |
nano.api.v2.webauth.get-session.failed.serverError | 服务端临时故障 | 稍后重试,持续失败请联系运营方 |
Scope 说明
目前仅支持一种 scope:access_token,表示申请获取玩家的第三方授权令牌。授权完成后,Notanote 会生成一个专用于第三方接口的 access_token,并通过回调地址回传给你。
回调地址收到的 query 参数:
| 参数 | 说明 |
|---|---|
name | 玩家的 Notanote 用户名 |
access_token | 第三方授权令牌 |
state | 你在第一步传入的 state,原样回传 |
access_token 权限隔离
access_token 仅限第三方接口使用,无法访问 Notanote 核心接口(如账号、用户、应用管理等)。即使令牌泄露,影响范围也只限于第三方接口,玩家核心数据不受影响。
| 接口类别 | access_token 能否访问 |
|---|---|
| 第三方接口 | 是 |
| 核心接口 | 否 |
| WebAuth 接口 | 否(无法用于续期) |
安全注意事项
接入 WebAuth 时请务必遵循以下安全规范,否则可能导致应用被冒充、玩家数据泄露等严重后果。
1. SecretKey 仅限服务端
SecretKey 禁止写入:
- 前端代码(包括编译后的产物)
- 客户端配置文件
- 版本控制系统(Git)
- 客户端可读的 LocalStorage / Cookie
泄露后攻击者可以冒充你的应用发起任意请求。建议通过环境变量或密钥管理服务(KMS)注入。
2. 必须校验 state
你的 callback 收到请求后,务必校验 state 与步骤一中发出的一致。如果不一致,说明这不是你发起的授权,应当拒绝。这是防御 CSRF 攻击的关键手段。
js
if (receivedState !== yourOriginalState) {
// 拒绝这次回调,可能遭到 CSRF 攻击
return;
}最佳实践:
state必须由服务端生成(不要在前端生成)state使用加密安全的随机数,长度至少 16 字符state一次性使用,校验通过后立即删除- 在
auth-session有效期内(5 分钟)必须完成校验
3. auth-session 一次性使用
auth-session 在玩家确认授权后立即作废,无法重放。即使攻击者截获了 auth-session,也无法用它重复发起授权。
4. auth-session 短 TTL
auth-session 有效期仅 5 分钟,降低泄露风险。你的服务端换取 auth-session 后应尽快引导玩家完成授权,避免会话过期导致授权失败。
5. 玩家身份二次验证
授权页会要求玩家输入 Notanote 账号密码,确保是玩家本人操作,而非攻击者伪造。
6. 无 SSRF 风险
Notanote 服务端不主动请求 callback,回调由玩家浏览器跳转完成。攻击者无法通过伪造 callback 让 Notanote 服务端扫描你的内网。
7. access_token 暴露处理
浏览器跳转时 access_token 会出现在地址栏和历史记录中。你的 callback 页面应:
- 在接收后立即用
access_token完成后续操作 - 引导玩家离开 callback 页面,避免 token 持续暴露