Initial FastAPI admin auth scaffold

This commit is contained in:
2026-06-05 17:10:30 +08:00
commit 5635da9ea5
65 changed files with 1407 additions and 0 deletions

145
README.md Normal file
View File

@@ -0,0 +1,145 @@
# py_server
这是一个 FastAPI 异步 API 项目骨架,分层方式参考了 Hyperf 项目里的 `server/app`
## 分层对应
| Hyperf | FastAPI 当前项目 | 作用 |
| --- | --- | --- |
| `Controller/Admin` | `app/controller/admin` | 接收请求,调用 service |
| `Service/Admin` | `app/service/admin` | 业务逻辑 |
| `Common/Repository` | `app/common/repository` | 数据访问 |
| `Model` | `app/model` | 数据模型 |
| `Middleware/Admin` | `app/middleware/admin` | admin token 和权限校验 |
| `Lib/Jwt` | `app/lib/jwt` | JWT 签发、解析、黑名单 |
| `Request/Admin` | `app/request/admin` | 请求参数校验 |
| `Constants` | `app/constants` | 状态码和业务常量 |
| `Lib/Return` | `app/lib/response` | 统一返回结构 |
> Python 里 `return` 是关键字,所以参考 Hyperf 的 `Lib/Return` 在这里命名为 `lib/response`。
## 启动
```bash
.venv/bin/uvicorn app.main:app --reload
```
默认启动时会自动创建 SQLite 开发库,并创建一个 admin 用户:
- username: `admin`
- password: `admin`
本地配置可以复制:
```bash
cp .env.example .env
```
## Admin 登录接口
### 登录
```http
POST /admin/login/login
Content-Type: application/json
{
"username": "admin",
"password": "admin"
}
```
返回:
```json
{
"code": 0,
"message": "success",
"data": {
"access_token": "...",
"refresh_token": "...",
"expire_at": 3600
}
}
```
### 刷新 token
```http
POST /admin/login/refresh
Authorization: Bearer <refresh_token>
```
刷新成功后会签发新的 `access_token``refresh_token`,并把旧的 `refresh_token` 加入黑名单,防止重复刷新。
### 当前 admin 用户
```http
GET /admin/profile/current
Authorization: Bearer <access_token>
```
## JWT 逻辑
当前实现和参考 Hyperf 项目保持同样思路:
1. 登录成功后同时签发 `access_token``refresh_token`
2. 普通 admin 接口只接受 `access_token`
3. `/admin/login/refresh` 只接受 `refresh_token`
4. refresh 成功后,把旧 refresh token 加入黑名单。
5. token 会校验签名、过期时间、issuer 和 token 类型。
token 读取顺序和 Hyperf 中间件一致:
1. `Authorization: Bearer <token>`
2. `token` header
3. query string: `?token=...`
## FastAPI 依赖注入
Controller 里这段:
```python
service: LoginService = Depends(get_login_service)
```
可以理解为 FastAPI 版的 Hyperf 容器注入。
请求进来时FastAPI 会先调用 `get_login_service()`,把创建好的 `LoginService` 传给 `service` 参数。
`get_login_service()` 内部会继续组装:
- `AdminUserRepository`
- `BaseTokenService`
- `AdminReturn`
所以 controller 只负责接收请求和调用 service。
## `@lru_cache` 的作用
`app/core/dependencies.py` 里的:
```python
@lru_cache
def get_database() -> Database:
return Database(get_settings().database_path)
```
表示第一次调用时创建对象,后面再次调用时直接复用第一次创建的对象。
在这个项目里,它的作用类似 Hyperf 容器里的共享服务/单例服务。比如 JWT 黑名单必须复用同一个对象,否则旧 refresh token 加入黑名单后,下一次请求就查不到了。
## 测试
```bash
.venv/bin/python -m compileall app tests
.venv/bin/python -m unittest tests.test_admin_login_flow
```
测试覆盖:
- admin 登录成功
- access token 访问当前用户成功
- refresh token 换新 token 成功
- 旧 refresh token 复用失败
- access token 调用 refresh 接口失败