Implement full media crawler workflow with Flask backend and Vue frontend.

Add TMDB search and media detail pages, HDHive resource ingestion flow, unified error handling, Docker single-container runtime, and project docs/config updates for local deployment.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
renjue
2026-05-09 16:16:18 +08:00
parent d3550bf79b
commit 82581d2949
49 changed files with 4959 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
# 认证与授权
## API Key 认证
所有 OpenAPI 请求都必须携带 `X-API-Key`
```http
X-API-Key: your-api-key
```
### 请求示例
```bash
curl -H "X-API-Key: your-api-key" https://hdhive.com/api/open/ping
```
## 用户身份来源
业务接口需要能确定调用用户。系统按以下顺序识别用户:
1. `Authorization: Bearer <OpenAPI 用户 Access Token>`:第三方应用授权后获得,必须属于当前应用。
2. `Authorization: Bearer <站内用户 JWT>`:站内登录态 Token。
3. API Key 绑定用户:个人 API Key 或管理员绑定用户的 OpenAPI 应用可回退到绑定用户。
`meta` 类接口如果无法确定用户,会返回 `OPENAPI_USER_REQUIRED`
## 第三方应用授权流程
第三方应用应使用管理员创建的 OpenAPI 应用完成授权:
1. 管理员创建 OpenAPI 应用配置应用名称、绑定用户、scope、IP 策略、回调地址等。
2. 第三方应用引导用户进入前端授权页 `/openapi/authorize`,并传入 `client_id``redirect_uri``scope``state`
3. 用户确认授权后HDHive 前端调用 `POST /api/public/openapi/oauth/authorize`,后端以 JSON 返回一次性授权码。
4. HDHive 前端把用户重定向到第三方 `redirect_uri`,并在 query 中追加 `code` 和原始 `state`
5. 第三方应用服务端用授权码调用 `POST /api/public/openapi/oauth/token` 换取用户 Access Token 和 Refresh Token。
6. 调用业务接口时同时传入应用 Secret 和用户 Access Token。
```http
X-API-Key: app-secret
Authorization: Bearer user-access-token
```
### 用户授权页
第三方应用应把用户跳转到站点前端授权页,而不是直接展示后端 API
```text
https://hdhive.com/openapi/authorize?client_id=app_xxx&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback&scope=query%20unlock&state=opaque-state
```
| 参数 | 必填 | 说明 |
|---|---|---|
| `client_id` | 是 | OpenAPI 应用公开 Client ID不是 Secret |
| `redirect_uri` | 是 | 回调地址,必须在应用配置的回调地址列表内 |
| `scope` | 否 | 请求的用户授权 scope空格分隔为空时按应用允许范围处理 |
| `state` | 否 | 第三方应用自定义状态,建议用于 CSRF 防护和回跳上下文 |
### 授权码换 Token
后端换取 Token 时必须使用应用 Secret
```bash
curl -X POST https://hdhive.com/api/public/openapi/oauth/token \\
-H "X-API-Key: app-secret" \\
-H "Content-Type: application/json" \\
-d '{
"grant_type": "authorization_code",
"code": "authorization-code",
"redirect_uri": "https://client.example.com/callback"
}'
```
返回的 `access_token` 用于业务 OpenAPI 调用,`refresh_token` 用于刷新用户授权 Token。
`redirect_uri` 在换取 Token 时不会触发跳转,它是授权码安全校验字段,必须与创建授权码时传入的 `redirect_uri` 完全一致。后端会用它确认授权码确实来自同一次授权请求,避免授权码被截获后在其他回调上下文中兑换。
### 授权码回调形式
用户确认授权后,第三方应用收到的是浏览器跳转请求:
```text
https://client.example.com/callback?code=authorization-code&state=opaque-state
```
`code` 是一次性授权码,第三方应用应该在自己的服务端用应用 Secret 换取 Token不要在浏览器里暴露应用 Secret。
## Scope
| scope | 说明 | 典型能力 |
|---|---|---|
| `meta` | 元信息接口 | 健康检查、配额、用量查询 |
| `query` | 查询接口 | 资源查询、分享详情、资源链接检查 |
| `write` | 写入接口 | 创建、更新、删除分享 |
| `unlock` | 解锁接口 | 解锁资源并获取链接 |
| `vip` | VIP 接口 | 用户信息、签到、VIP 用量 |
应用必须拥有对应 scope用户授权 Token 如果限制了 scope也必须包含对应 scope。
## 认证错误码
| 错误码 | HTTP 状态码 | 说明 |
|---|---|---|
| `MISSING_API_KEY` | 401 | 未提供 `X-API-Key` |
| `INVALID_API_KEY` | 401 | API Key 无效或不存在 |
| `DISABLED_API_KEY` | 401 | API Key 已被禁用 |
| `EXPIRED_API_KEY` | 401 | API Key 已过期 |
| `INVALID_OPENAPI_USER_TOKEN` | 401 | OpenAPI 用户 Token 无效 |
| `OPENAPI_TOKEN_APP_MISMATCH` | 401 | 用户 Token 不属于当前应用 |
| `OPENAPI_USER_REQUIRED` | 403 | 业务接口缺少用户身份 |
| `SCOPE_NOT_ALLOWED` | 403 | 应用未授权该接口组 |
| `USER_SCOPE_NOT_ALLOWED` | 403 | 用户授权 Token scope 不足 |
| `VIP_REQUIRED` | 403 | 当前用户不满足 Premium 要求 |