117 lines
3.4 KiB
Markdown
117 lines
3.4 KiB
Markdown
|
|
# soul-api 管理端登录判断与权限校验
|
|||
|
|
|
|||
|
|
## 一、有没有登录的依据(JWT)
|
|||
|
|
|
|||
|
|
**依据:请求中的 JWT。优先从 `Authorization: Bearer <token>` 读取,兼容从 Cookie `admin_session` 读取。**
|
|||
|
|
|
|||
|
|
| 项目 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| 推荐方式 | 请求头 `Authorization: Bearer <JWT>` |
|
|||
|
|
| 兼容方式 | Cookie 名 `admin_session`,值为 JWT 字符串 |
|
|||
|
|
| JWT 算法 | HS256,密钥为 `ADMIN_SESSION_SECRET` |
|
|||
|
|
| 有效期 | 7 天(exp claim) |
|
|||
|
|
| 载荷 | sub=admin, username, role=admin |
|
|||
|
|
| 校验 | 验签 + 未过期 → 视为已登录 |
|
|||
|
|
|
|||
|
|
- 配置:`ADMIN_USERNAME` / `ADMIN_PASSWORD` 用于登录校验;`ADMIN_SESSION_SECRET` 用于签发/校验 JWT。
|
|||
|
|
- 未带有效 JWT → 401。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、权限校验设计(路由分层)
|
|||
|
|
|
|||
|
|
- **不校验登录**:只做业务逻辑(登录、登出、鉴权检查)
|
|||
|
|
- `GET /api/admin` → 鉴权检查(读 Cookie,有效 200 / 无效 401)
|
|||
|
|
- `POST /api/admin` → 登录(校验账号密码,写 Cookie)
|
|||
|
|
- `POST /api/admin/logout` → 登出(删 Cookie)
|
|||
|
|
|
|||
|
|
- **必须已登录**:挂 `AdminAuth()` 中间件,从请求读 `admin_session` 并验签+过期,不通过直接 401,不进入 handler
|
|||
|
|
- `/api/admin/*`(如 chapters、content、withdrawals、settings 等)
|
|||
|
|
- `/api/db/*`
|
|||
|
|
|
|||
|
|
- **其它**:如 `/api/miniprogram/*`、`/api/book/*` 等不加 AdminAuth,按各自接口鉴权(如小程序 token)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、框图
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TB
|
|||
|
|
subgraph 前端["soul-admin 前端"]
|
|||
|
|
A[用户打开后台 / 请求接口]
|
|||
|
|
A --> B{请求类型}
|
|||
|
|
B -->|登录| C[POST /api/admin]
|
|||
|
|
B -->|登出| D[POST /api/admin/logout]
|
|||
|
|
B -->|进后台前检查| E[GET /api/admin]
|
|||
|
|
B -->|业务接口| F[GET/POST /api/admin/xxx]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph 请求["每次请求"]
|
|||
|
|
G[浏览器自动携带 Cookie: admin_session]
|
|||
|
|
G --> H[发往 soul-api]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph soul-api["soul-api 路由"]
|
|||
|
|
I["/api/admin 三条(无中间件)"]
|
|||
|
|
J["/api/admin/* 与 /api/db/*"]
|
|||
|
|
J --> K[AdminAuth 中间件]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph 鉴权["AdminAuth 与 AdminCheck 逻辑"]
|
|||
|
|
K --> L[从请求读 Cookie admin_session]
|
|||
|
|
L --> M{有 Cookie?}
|
|||
|
|
M -->|无| N[401 未授权]
|
|||
|
|
M -->|有| O[解析 exp.signature]
|
|||
|
|
O --> P{未过期 且 验签通过?}
|
|||
|
|
P -->|否| N
|
|||
|
|
P -->|是| Q[放行 / 返回 200]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
C --> I
|
|||
|
|
D --> I
|
|||
|
|
E --> I
|
|||
|
|
F --> J
|
|||
|
|
H --> soul-api
|
|||
|
|
I --> E2[GET: 同鉴权逻辑 200/401]
|
|||
|
|
I --> C2[POST: 校验账号密码 写 Cookie]
|
|||
|
|
I --> D2[POST: 清 Cookie]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**路由与中间件关系(框线):**
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart LR
|
|||
|
|
subgraph 无鉴权["不经过 AdminAuth"]
|
|||
|
|
R1[GET /api/admin]
|
|||
|
|
R2[POST /api/admin]
|
|||
|
|
R3[POST /api/admin/logout]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph 需登录["经过 AdminAuth"]
|
|||
|
|
R4["/api/admin/chapters"]
|
|||
|
|
R5["/api/admin/withdrawals"]
|
|||
|
|
R6["/api/admin/settings"]
|
|||
|
|
R7["/api/db/*"]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph 中间件["AdminAuth()"]
|
|||
|
|
M[读 Cookie → 验 token → 通过/401]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
H1[直接进 handler]
|
|||
|
|
H2[通过则进 handler]
|
|||
|
|
无鉴权 --> H1
|
|||
|
|
需登录 --> M --> H2
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、相关代码位置
|
|||
|
|
|
|||
|
|
| 作用 | 位置 |
|
|||
|
|
|------|------|
|
|||
|
|
| JWT 签发/校验/从请求取 token | `internal/auth/adminjwt.go` |
|
|||
|
|
| 登录、登出、GET 鉴权检查 | `internal/handler/admin.go` |
|
|||
|
|
| 管理端中间件 | `internal/middleware/admin_auth.go` |
|
|||
|
|
| 路由挂载 | `internal/router/router.go`(api.Group + admin.Use(AdminAuth())) |
|