Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
701 lines
17 KiB
Markdown
701 lines
17 KiB
Markdown
# 涩花塘磁力助手 - 项目架构与部署说明
|
||
|
||
> 更新时间:2026-03-14
|
||
> 说明:本文档描述当前项目的整体架构、核心数据流、缓存策略、云同步设计、线上部署信息(**不包含任何敏感凭据**),以及当前已知问题与优化方向。
|
||
|
||
---
|
||
|
||
## 1. 项目概览
|
||
|
||
本项目由两部分组成:
|
||
|
||
1. **Chrome 扩展端**
|
||
负责在涩花塘论坛页面中:
|
||
- 识别列表页 / 帖子页
|
||
- 批量抓取帖子与磁力链接
|
||
- 本地缓存帖子、范围快照、页快照、磁力结果
|
||
- 展示搜索结果、缓存总览、收藏夹、云同步入口
|
||
|
||
2. **云端共享缓存服务**
|
||
负责:
|
||
- 共享线程缓存(shared thread cache)
|
||
- 共享范围缓存(shared coverage cache)
|
||
- 共享页缓存(shared page cache)
|
||
- 覆盖规划(coverage planning)
|
||
- 私有保险柜(vault)
|
||
- 账号注册 / 登录 / 鉴权
|
||
|
||
---
|
||
|
||
## 2. 目录结构
|
||
|
||
### 扩展端根目录
|
||
|
||
- `manifest.json`:Chrome 扩展清单(MV3)
|
||
- `content.js`:内容脚本,挂载 UI、执行抓取、合并缓存、结果展示
|
||
- `background.js`:Service Worker,负责 IndexedDB、本地状态、云接口、跨页请求
|
||
- `popup.html` / `popup.js`:扩展独立云同步中心 + 快捷复制入口
|
||
|
||
### 服务端目录
|
||
|
||
- `server/package.json`:服务端依赖与脚本
|
||
- `server/src/index.js`:Fastify 入口
|
||
- `server/src/config.js`:环境变量配置
|
||
- `server/src/db.js`:MySQL 连接池
|
||
- `server/src/redis.js`:Redis 连接与 JSON 缓存
|
||
- `server/src/crypto.js`:AES-GCM 加密与哈希
|
||
- `server/src/auth.js`:认证辅助逻辑
|
||
- `server/src/routes/auth.js`:注册 / 登录 / me / logout
|
||
- `server/src/routes/vault.js`:私有保险柜 push / pull
|
||
- `server/src/routes/shared-cache.js`:共享缓存查找 / 写入 / coverage planning
|
||
- `server/sql/001_init.sql`:数据库初始化表结构
|
||
|
||
---
|
||
|
||
## 3. 扩展端架构
|
||
|
||
### 3.1 页面层(content.js)
|
||
|
||
`content.js` 负责:
|
||
|
||
- 判断当前页面是:
|
||
- 列表页(forumdisplay / forum-x-y.html / normalthread tbody)
|
||
- 帖子页(thread-xxx / tid=xxx)
|
||
- 创建浮动面板 UI
|
||
- 管理:
|
||
- 关键词搜索
|
||
- 页码范围
|
||
- 速度模式
|
||
- 结果列表
|
||
- 收藏页
|
||
- 缓存页
|
||
- 云同步页入口
|
||
- 调用后台:
|
||
- 读取 / 保存本地缓存
|
||
- 读取 / 保存进度状态
|
||
- 触发云同步相关动作
|
||
|
||
### 3.2 后台层(background.js)
|
||
|
||
`background.js` 是当前项目的核心调度层,负责:
|
||
|
||
- IndexedDB 缓存存取
|
||
- 云缓存接口调用
|
||
- 共享缓存 planning 调用
|
||
- 上传抑制(hash 去重 + TTL 节流)
|
||
- 本地历史缓存回填到云端
|
||
- 私有保险柜加解密
|
||
- 云账号登录状态维护
|
||
|
||
### 3.3 本地存储层
|
||
|
||
当前本地存储分三类:
|
||
|
||
1. **IndexedDB(结构化缓存)**
|
||
- `threads`
|
||
- `coverages`
|
||
- `pageCoverages`
|
||
|
||
2. **chrome.storage.local(扩展私有存储)**
|
||
- 收藏夹
|
||
- 搜索历史
|
||
- 云同步状态
|
||
- 上传元数据去重表
|
||
- 进度状态
|
||
|
||
3. **运行时内存态**
|
||
- 当前抓取状态
|
||
- session backup 临时状态
|
||
|
||
---
|
||
|
||
## 4. 服务端架构
|
||
|
||
### 4.1 服务端职责
|
||
|
||
云服务现在不仅是“存数据”,还承担:
|
||
|
||
- 共享缓存存储
|
||
- 去重写入
|
||
- coverage planning
|
||
- Redis 缓存 planning 结果
|
||
- 账号认证
|
||
- 私有保险柜同步
|
||
|
||
### 4.2 路由职责
|
||
|
||
#### 认证
|
||
- `POST /api/auth/register`
|
||
- `POST /api/auth/login`
|
||
- `GET /api/auth/me`
|
||
- `POST /api/auth/logout`
|
||
|
||
#### 私有保险柜
|
||
- `POST /api/vault/push`
|
||
- `POST /api/vault/pull`
|
||
|
||
#### 共享缓存
|
||
- `POST /api/shared-cache/threads/lookup`
|
||
- `POST /api/shared-cache/threads/upsert`
|
||
- `POST /api/shared-cache/coverages/lookup`
|
||
- `POST /api/shared-cache/coverages/upsert`
|
||
- `POST /api/shared-cache/pages/lookup`
|
||
- `POST /api/shared-cache/pages/upsert`
|
||
- `POST /api/shared-cache/coverages/plan`
|
||
|
||
#### 健康检查
|
||
- `GET /health`
|
||
- `GET /ready`
|
||
|
||
---
|
||
|
||
## 5. 本地缓存模型
|
||
|
||
### 5.1 `threads`
|
||
存储唯一帖子级信息:
|
||
|
||
- `forumKey`
|
||
- `threadKey`
|
||
- `url`
|
||
- `title`
|
||
- `lastSeenAt`
|
||
- `magnets`
|
||
- `lastMagnetSyncAt`
|
||
|
||
特点:
|
||
- 同一板块 + 同一帖子只保留一份
|
||
- 线程磁链缓存优先从这里命中
|
||
|
||
### 5.2 `coverages`
|
||
存储范围级快照:
|
||
|
||
- `forumKey`
|
||
- `startPage`
|
||
- `endPage`
|
||
- `strategy`
|
||
- `frontRefreshPages`
|
||
- `threadKeys`
|
||
|
||
特点:
|
||
- 表示某个页范围对应的帖子集合
|
||
- 用于 exact coverage / shifted coverage / 历史 coverage 碎片复用
|
||
|
||
### 5.3 `pageCoverages`
|
||
存储页级快照:
|
||
|
||
- `forumKey`
|
||
- `page`
|
||
- `threadKeys`
|
||
|
||
特点:
|
||
- 用来组装连续页块
|
||
- 当前大范围命中优化的重要基础
|
||
|
||
---
|
||
|
||
## 6. 云端缓存模型
|
||
|
||
### 6.1 共享线程缓存 `shared_thread_cache`
|
||
- 唯一键:`(forum_key, thread_key)`
|
||
- 数据库存储加密:AES-GCM
|
||
- 用于跨用户复用帖子级磁链结果
|
||
|
||
### 6.2 共享范围缓存 `shared_coverage_cache`
|
||
- 唯一键:`(forum_key, start_page, end_page, strategy)`
|
||
- 用于整段范围的覆盖规划
|
||
|
||
### 6.3 共享页缓存 `shared_page_cache`
|
||
- 唯一键:`(forum_key, page)`
|
||
- 用于连续页块拼装
|
||
|
||
### 6.4 私有保险柜 `vault_items`
|
||
- 用户级密文存储
|
||
- 当前用于:
|
||
- 收藏夹
|
||
- 搜索历史
|
||
- UI 设置
|
||
- 进度状态
|
||
|
||
---
|
||
|
||
## 7. 抓取流程(当前实际运行路径)
|
||
|
||
### 7.1 点击“开始获取”后的流程
|
||
|
||
1. 读取页码范围 / 关键词 / 速度配置
|
||
2. 构建 `searchContext`
|
||
3. 显示:
|
||
- `正在规划缓存:检查本地缓存 / 云端规划 / 复用块...`
|
||
4. 调用 `getCachedCoveragePlan(...)`
|
||
5. 依次判断:
|
||
- exact coverage
|
||
- assembled page coverage
|
||
- 服务端 planning
|
||
- cachedBlocks
|
||
- shiftedCoverage
|
||
6. 对缺口区间执行 live 抓取
|
||
7. 结果与缓存合并后,再写回本地与云端
|
||
|
||
### 7.2 实际搜索执行路径
|
||
|
||
主要函数:
|
||
|
||
- `fetchFromPage(...)`
|
||
- `fetchLivePageRange(...)`
|
||
- `processCachedThreadBatch(...)`
|
||
- `applyCachedMagnetHits(...)`
|
||
|
||
---
|
||
|
||
## 8. 去重与上传抑制策略
|
||
|
||
### 8.1 本地去重
|
||
|
||
- 线程去重:`normalizeCachedThreads()`
|
||
- 磁链去重:`normalizeMagnetList()`
|
||
- coverage 合并去重:`mergeCoverageThreads()`
|
||
- coverage 保存前合并:`mergeCoverageThreadLists()`
|
||
|
||
### 8.2 云端去重
|
||
|
||
数据库唯一索引 + `ON DUPLICATE KEY UPDATE`
|
||
|
||
### 8.3 上传抑制
|
||
|
||
本地维护 upload meta:
|
||
|
||
- `threads`
|
||
- `coverages`
|
||
- `pages`
|
||
|
||
每类记录:
|
||
- `payloadHash`
|
||
- `lastUploadedAt`
|
||
|
||
TTL:
|
||
|
||
- 线程:10 分钟
|
||
- 页:30 分钟
|
||
- 范围:60 分钟
|
||
|
||
作用:
|
||
- 降低重复上传
|
||
- 降低重复加密
|
||
- 降低数据库写入压力
|
||
|
||
---
|
||
|
||
## 9. 当前“智能更新”逻辑
|
||
|
||
### 已实现
|
||
|
||
1. front refresh(从第一页开始时可刷新前段)
|
||
2. shiftedCoverage 复用
|
||
3. page cache block 复用
|
||
4. intersecting coverage fragments 复用
|
||
5. 服务端 coverage planning
|
||
6. Redis 缓存 planning 结果
|
||
|
||
### 当前仍不够理想的点
|
||
|
||
1. **thread cache 很多,但未完全反向沉淀成 page/coverage 索引**
|
||
这会导致“明明有很多历史线程缓存,但大范围规划不够聪明”。
|
||
|
||
2. **coverage 合并仍然偏保守**
|
||
少量前页更新后,虽然已经补了历史 coverage 合并,但仍建议继续增强“旧帖保留连续性”。
|
||
|
||
3. **前段刷新策略仍是经验型策略**
|
||
当前已从“固定刷新前 20 页”改为“前面没有缓存覆盖才刷新”,但仍属于启发式策略。
|
||
|
||
4. **启动前规划仍然是同步等待**
|
||
现在已经加了状态提示,但未来可以做:
|
||
- 本地快速规划优先
|
||
- 云端规划异步补充
|
||
|
||
---
|
||
|
||
## 10. 线上部署信息(不含敏感凭据)
|
||
|
||
### 服务器基础信息
|
||
|
||
- 公网 IP:`47.238.173.98`
|
||
- 域名:`s.52oai.com`
|
||
- 系统:CentOS 7(当前会话已确认)
|
||
- 部署方式:Nginx + PM2 + Node.js + MySQL + Redis
|
||
- 面板:宝塔面板(BT Panel)
|
||
|
||
### 当前服务端组成
|
||
|
||
- Nginx:反向代理入口
|
||
- Node 服务:`magnet-cloud-cache`
|
||
- PM2:进程守护
|
||
- MySQL:主数据存储
|
||
- Redis:coverage planning 结果缓存
|
||
|
||
### 线上访问入口
|
||
|
||
- `https://s.52oai.com/health`
|
||
- `https://s.52oai.com/ready`
|
||
|
||
### Redis 状态
|
||
|
||
当前已验证:
|
||
|
||
- Redis 可连接
|
||
- 可写入/读取 JSON
|
||
- coverage planning key 已落库
|
||
|
||
---
|
||
|
||
## 11. 当前安全边界
|
||
|
||
### 已完成的安全改造
|
||
|
||
1. 云同步登录/注册 UI 已迁移到扩展独立页面
|
||
2. 收藏/搜索历史已迁移到扩展私有存储
|
||
3. session 进度备份已不再依赖页面 `sessionStorage`
|
||
4. shared-cache 写接口已加写入令牌鉴权
|
||
5. shared-cache 已避免旧写覆盖新写
|
||
|
||
### 仍建议后续加强
|
||
|
||
1. `vaultKeyBase64` 改为 session-only
|
||
2. auth/vault/shared-cache 更细粒度限流
|
||
3. 服务端请求体大小再收紧
|
||
4. 共享缓存写审计日志
|
||
|
||
---
|
||
|
||
## 12. 当前最值得继续优化的方向
|
||
|
||
### P1 - 正确性优先
|
||
|
||
1. **thread cache 反向沉淀成 page/coverage 索引**
|
||
这是目前提升“大范围缓存命中率”的最高价值项。
|
||
|
||
2. **coverage 合并策略继续增强**
|
||
尤其是前段少量更新后,历史旧帖不应被挤出当前范围搜索。
|
||
|
||
3. **规划器结果可观测化**
|
||
建议增加 debug summary:
|
||
- 命中 exact coverage
|
||
- 命中 page blocks 数
|
||
- 命中 intersecting coverage 数
|
||
- 实际缺口页数
|
||
|
||
### P2 - 性能优先
|
||
|
||
1. 本地快速规划优先,云端 planning 异步补充
|
||
2. planning 结果本地短时缓存
|
||
3. 回填队列分批化
|
||
|
||
---
|
||
|
||
## 12.1 当前抓取合并 / 去重 / 智能更新逻辑复盘
|
||
|
||
### 一、当前逻辑里已经做对的部分
|
||
|
||
1. **线程级去重已经明确**
|
||
- 本地通过 `threadKey` 去重
|
||
- 云端通过 `(forum_key, thread_key)` 唯一约束去重
|
||
|
||
2. **磁链级去重已经明确**
|
||
- 本地通过 `normalizeMagnetList()` 去重
|
||
- 云端共享缓存目前按线程保存,磁链集合在单线程内部去重
|
||
|
||
3. **coverage 规划已经从“只看精确范围”进化为多层来源**
|
||
当前 `getCachedCoveragePlan()` 已经综合:
|
||
- exact coverage
|
||
- assembled page coverage
|
||
- 服务端 planning
|
||
- cachedBlocks(页块)
|
||
- intersecting coverages(相交范围碎片)
|
||
- shiftedCoverage
|
||
|
||
4. **上传抑制已经开始发挥作用**
|
||
- thread/page/coverage 都有 upload meta
|
||
- hash + TTL 可以减少重复上云
|
||
|
||
### 二、当前逻辑不够理想的核心点
|
||
|
||
#### 1. 线程缓存与页/范围索引仍然是“半脱节”
|
||
|
||
这是目前最关键的问题:
|
||
|
||
- `threads` 里可能已经积累了大量帖子与磁链
|
||
- 但这些历史数据没有系统性地回灌成:
|
||
- `pageCoverages`
|
||
- `coverages`
|
||
|
||
结果就是:
|
||
|
||
> 看起来缓存很多,但真正能参与“大范围规划”的缓存块不够多。
|
||
|
||
#### 2. 智能更新仍然偏启发式,而不是差异驱动
|
||
|
||
当前 front refresh / shiftedCoverage 还是基于:
|
||
|
||
- 从第 1 页开始时,倾向刷新前段
|
||
- 历史范围快照的最近性
|
||
|
||
但它缺少真正的:
|
||
|
||
- 基于“帖子是否变化”的差异判断
|
||
- 基于线程游标 / 内容指纹 / 页指纹 的更新模型
|
||
|
||
#### 3. coverage 合并虽然已经补强,但仍然不够结构化
|
||
|
||
当前已经补了:
|
||
|
||
- 保存新 coverage 前,合并历史相交 coverage 的线程
|
||
|
||
但这个策略仍是:
|
||
|
||
- 按线程集合合并
|
||
- 不是按“真实页结构”或“线程页位置偏移”合并
|
||
|
||
所以在论坛前段轻微更新时,仍可能出现:
|
||
|
||
- 范围快照连续性不足
|
||
- 旧帖可见性波动
|
||
|
||
#### 4. 服务端 planning 已加入,但仍然是“辅助规划器”
|
||
|
||
现在服务端已经能返回:
|
||
|
||
- `exactCoverage`
|
||
- `cachedBlocks`
|
||
- `shiftedCoverage`
|
||
|
||
但扩展端仍保留了大量本地规划逻辑,导致:
|
||
|
||
- 本地规划与服务端规划并存
|
||
- 逻辑复杂度上升
|
||
- 调试成本高
|
||
|
||
### 三、当前最值得优先继续优化的技术方向
|
||
|
||
#### A. `threads -> pageCoverages / coverages` 反向沉淀
|
||
|
||
这是正确性和命中率的第一优先级优化。
|
||
|
||
目标:
|
||
|
||
- 当系统手里已经有大量 thread cache 时
|
||
- 能定期 / 按需将其重建为:
|
||
- page coverage block
|
||
- coverage fragment
|
||
|
||
收益:
|
||
|
||
- “缓存明明很多却命中不上”的问题会明显缓解
|
||
|
||
#### B. 引入“线程或页面指纹”作为智能更新依据
|
||
|
||
例如:
|
||
|
||
- 页面线程列表 hash
|
||
- 范围线程集合 hash
|
||
- 线程集合版本号
|
||
|
||
这样 front refresh 就能从“经验刷新”变成:
|
||
|
||
- 先比对指纹
|
||
- 只有前段真的变化才刷新
|
||
|
||
#### C. 最终把 planning 统一到服务端主导
|
||
|
||
建议目标不是“双规划器”,而是:
|
||
|
||
- 服务端负责 coverage planning
|
||
- 扩展端只负责执行计划
|
||
- 本地逻辑只保留兜底回退
|
||
|
||
这样架构会明显更稳。
|
||
|
||
### P3 - 运维优先
|
||
|
||
1. 共享缓存保留策略 / 归档策略
|
||
2. 写入审计与异常监控
|
||
3. 密钥轮换机制
|
||
|
||
---
|
||
|
||
## 13. 当前版本的整体评价
|
||
|
||
### 已经具备的能力
|
||
|
||
- 本地线程 / 范围 / 页缓存
|
||
- 云端共享缓存
|
||
- 私有保险柜
|
||
- 上传抑制与 TTL 节流
|
||
- coverage planning + Redis planning cache
|
||
- 扩展端 UI / 云同步中心 / 收藏 / 搜索历史
|
||
|
||
### 当前最核心的短板
|
||
|
||
> 缓存数据已经很多,但“如何把这些缓存组织成最优复用计划”仍然不够强。
|
||
|
||
也就是说,当前系统最难的不是“存缓存”,而是:
|
||
|
||
> **把已有缓存规划成正确、完整、连续的搜索路径**
|
||
|
||
---
|
||
|
||
## 14. 文档使用建议
|
||
|
||
如果后续你继续迭代项目,建议把本文档当成:
|
||
|
||
1. **新人接手说明**
|
||
2. **线上部署说明**
|
||
3. **缓存/同步逻辑总览**
|
||
4. **后续重构路线图**
|
||
|
||
---
|
||
|
||
## 15. 敏感信息说明
|
||
|
||
本文档**不记录**以下信息:
|
||
|
||
- SSH 密码
|
||
- MySQL 密码
|
||
- write token
|
||
- 加密密钥
|
||
- `.env` 明文内容
|
||
|
||
这些信息应只保留在安全的部署环境与秘密管理系统中。
|
||
|
||
---
|
||
|
||
## 16. Chrome 分发与更新能力边界
|
||
|
||
结合当前平台限制和架构评估,下面是**真实可行**与**不可行**的边界。
|
||
|
||
### 16.1 对普通 Chrome 用户,不可直接做到的事
|
||
|
||
以下能力在普通非企业托管 Chrome 中,**不现实或不受支持**:
|
||
|
||
1. **从网站自动把扩展装进 Chrome**
|
||
2. **通过主页密码后,静默安装 CRX**
|
||
3. **普通用户使用自托管 CRX 自动更新**
|
||
|
||
也就是说:
|
||
|
||
> `s.52oai.com` 可以做“分发引导页”,但不能真正实现“输密码后自动装到 Chrome 里”。
|
||
|
||
### 16.2 最现实的分发方式
|
||
|
||
对于普通用户,最推荐:
|
||
|
||
1. **发布到 Chrome Web Store(建议 unlisted)**
|
||
2. `s.52oai.com` 做密码门禁页
|
||
3. 门禁通过后展示:
|
||
- CWS 安装链接
|
||
- 安装说明
|
||
- 使用说明
|
||
|
||
这样可以获得:
|
||
|
||
- 官方安装路径
|
||
- Chrome 自动更新
|
||
- 最低用户支持成本
|
||
|
||
### 16.3 自托管更新什么时候才成立
|
||
|
||
只有在以下场景,自托管更新才是现实方案:
|
||
|
||
- **企业托管 Chrome**
|
||
- 管理员通过策略安装
|
||
- 使用企业设备 / 组织统一管理浏览器
|
||
|
||
这不是普通公网用户场景。
|
||
|
||
### 16.4 当前项目建议的分发策略
|
||
|
||
如果未来要正式分发,推荐顺序:
|
||
|
||
1. **Chrome Web Store(最好 Unlisted)**
|
||
2. `s.52oai.com` 做密码门禁与引导页
|
||
3. 扩展内做“最低支持版本”检查
|
||
4. 如果版本太低,则提示用户去商店更新
|
||
|
||
### 16.5 站点密码的真实作用
|
||
|
||
主页密码(例如 `123456`)只能充当:
|
||
|
||
- 引导门槛
|
||
- 简单访问控制
|
||
- 降低无关访问
|
||
|
||
但它**不能视为真正安全边界**。真正的权限控制仍然必须放在:
|
||
|
||
- 后端账号系统
|
||
- API 鉴权
|
||
- 服务端授权逻辑
|
||
|
||
|
||
---
|
||
|
||
## 16. Chrome 分发与更新能力边界(部署到主页的现实约束)
|
||
|
||
### 16.1 对普通 Chrome 用户,不能直接做到的事
|
||
|
||
对于**普通、非企业托管**的 Chrome 用户,当前不支持:
|
||
|
||
1. 从 `s.52oai.com` 网页直接自动安装扩展
|
||
2. 从自有网站静默安装 CRX
|
||
3. 对普通用户使用自托管 CRX 做自动更新
|
||
|
||
也就是说:
|
||
|
||
> 网站可以做“入口页 / 密码门禁页 / 引导页”,但不能真正代替 Chrome 官方安装渠道完成自动安装。
|
||
|
||
### 16.2 对普通用户最现实的方案
|
||
|
||
最可行方案是:
|
||
|
||
1. 发布到 **Chrome Web Store(建议 Unlisted)**
|
||
2. `s.52oai.com` 作为密码门禁页
|
||
3. 输入密码后展示:
|
||
- Chrome Web Store 安装链接
|
||
- 使用说明
|
||
- 更新说明
|
||
|
||
这样可以获得:
|
||
|
||
- 标准安装体验
|
||
- Chrome 自动更新
|
||
- 最低的用户支持成本
|
||
|
||
### 16.3 自托管自动更新什么时候可行
|
||
|
||
只有在:
|
||
|
||
- 企业托管 Chrome
|
||
- 管理员策略安装
|
||
- 受管设备/受管浏览器环境
|
||
|
||
这种情况下,自托管 CRX + update manifest 才是现实路径。
|
||
|
||
### 16.4 当前项目推荐的分发模式
|
||
|
||
推荐顺序:
|
||
|
||
1. **Chrome Web Store(Unlisted)** 作为主分发渠道
|
||
2. `s.52oai.com` 做密码门禁 + 安装引导页
|
||
3. 扩展内调用服务端 `/ext/config`(后续可实现)检查最低支持版本
|
||
4. 如果版本过低,提示用户跳转到商店升级
|
||
|
||
### 16.5 密码门禁的真实作用
|
||
|
||
密码门禁只能起到:
|
||
|
||
- 隐藏安装入口
|
||
- 控制谁能看到链接
|
||
|
||
但它**不能视为真正的安全边界**。真正的权限控制必须放在:
|
||
|
||
- 后端账号体系
|
||
- API token / 登录态
|
||
- 服务器侧权限判断
|