security: external API - only ID+Secret auth, remove legacy key & JWT
- removed x-external-key (single key) auth path + getExternalKey - removed JWT passthrough in clientAuth (Bearer no longer accepted) - removed /auth/login (JWT endpoint) and /my-tickets (JWT-only) - clientAuth now mandatory: missing/invalid/disabled client -> 401 (closed the 'no config = allow all' authorization bypass) - moved /auth/register BEHIND clientAuth (was anonymous abuse surface) - clients mgmt endpoints keep authenticate + role check (admin UI) - docs + UI copy updated to single auth method - verified: 30 checks incl. full-tree scan for legacy key refs
This commit is contained in:
13
docs/API.md
13
docs/API.md
@@ -331,10 +331,7 @@ Base URL: `http://<host>:3100/api`
|
||||
|
||||
| 端点 | 认证 | 说明 |
|
||||
|------|------|------|
|
||||
| POST /external/auth/register | — | 插件注册(邮箱验证链接) |
|
||||
| POST /external/auth/login | — | 插件登录,返回 JWT |
|
||||
| GET /external/my-tickets | Bearer | 我的工单列表(limit ≤50) |
|
||||
| GET /external/my-tickets/:id | Bearer | 我的工单详情 |
|
||||
| POST /external/auth/register | client | 插件注册(需客户端凭据;邮箱验证链接) |
|
||||
| POST /external/tickets | client | 提交工单(带 `server` 可选;返回 id + tracking_token) |
|
||||
| GET /external/tickets/track?token= | client | 按追踪码查工单状态+回复(提交→处理→结束全流程) |
|
||||
| GET /external/all-tickets | client | 全部工单(分页 page/limit ≤200,可按 `server`/`status`/`type` 过滤) |
|
||||
@@ -349,13 +346,11 @@ Base URL: `http://<host>:3100/api`
|
||||
| PUT /external/clients/:id | Bearer(owner/admin) | 启用/停用客户端 |
|
||||
| DELETE /external/clients/:id | Bearer(owner/admin) | 删除客户端 |
|
||||
|
||||
### 外部鉴权(三选一)
|
||||
### 外部鉴权(唯一方式)
|
||||
|
||||
| 方式 | 请求头 | 适用 |
|
||||
| 方式 | 请求头 | 说明 |
|
||||
|------|--------|------|
|
||||
| 多客户端(推荐) | `x-api-client-id` + `x-api-secret` | QQ机器人等外部系统,后台可创建/停用多个客户端 |
|
||||
| 旧版单 key | `x-external-key` | 兼容旧部署(`config.external_api_key`) |
|
||||
| 用户 JWT | `Authorization: Bearer <jwt>` | 插件/已登录用户 |
|
||||
| ID + Secret(唯一) | `x-api-client-id` + `x-api-secret` | 后台可创建/停用多个客户端;无凭据或凭据错误一律 401 |
|
||||
|
||||
### 子服务器定位(`server` 参数)
|
||||
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
|
||||
---
|
||||
|
||||
## 一、鉴权(三种方式,任选其一)
|
||||
|
||||
### 方式 A:ID + Secret(推荐,多客户端)
|
||||
## 一、鉴权(唯一方式:ID + Secret)
|
||||
|
||||
在站点后台 →「外部API」页面创建客户端,获得一对凭据:
|
||||
|
||||
@@ -20,6 +18,7 @@ Secret: s_9f8e7d6c5b4a39281726354a1b2c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e
|
||||
```
|
||||
|
||||
> ⚠️ Secret 只在创建时显示一次,请立即保存。支持创建多个客户端、单独停用/删除,互不影响。
|
||||
> 无凭据 / 凭据错误 / 客户端停用 → 一律返回 `401`。
|
||||
|
||||
调用时在请求头携带:
|
||||
|
||||
@@ -28,18 +27,6 @@ Secret: s_9f8e7d6c5b4a39281726354a1b2c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e
|
||||
| `x-api-client-id` | 你的 Client ID |
|
||||
| `x-api-secret` | 你的 Secret |
|
||||
|
||||
### 方式 B:旧版单 Key(兼容)
|
||||
|
||||
| 请求头 | 值 |
|
||||
|--------|-----|
|
||||
| `x-external-key` | 部署时配置的 external_api_key |
|
||||
|
||||
### 方式 C:用户 JWT(仅限插件)
|
||||
|
||||
| 请求头 | 值 |
|
||||
|--------|-----|
|
||||
| `Authorization` | `Bearer <JWT>`(来自 `POST /api/external/auth/login`) |
|
||||
|
||||
---
|
||||
|
||||
## 二、快速开始(Python / Node 示例)
|
||||
@@ -324,9 +311,10 @@ GET /api/external/stats?server=
|
||||
|
||||
## 六、鉴权失败排查
|
||||
|
||||
1. **401 未授权**:检查 `x-api-client-id` / `x-api-secret` 是否与创建时一致;客户端是否被停用;secret 是否完整无换行空格。
|
||||
2. **客户端被停用**:后台「外部API」→ 启用。
|
||||
3. **需要多个客户端**:后台可创建多个,分别用于机器人 / 插件 / 统计面板,互不影响;删除即立即失效。
|
||||
1. **401 缺少凭据**:请求必须携带 `x-api-client-id` 与 `x-api-secret` 两个请求头。
|
||||
2. **401 客户端鉴权失败**:检查 Client ID / Secret 是否与创建时一致;secret 是否完整无换行空格;客户端是否被停用。
|
||||
3. **客户端被停用**:后台「外部API」→ 启用。
|
||||
4. **需要多个客户端**:后台可创建多个,分别用于机器人 / 插件 / 统计面板,互不影响;删除即立即失效。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user