142 lines
5.5 KiB
Markdown
142 lines
5.5 KiB
Markdown
# 登录鉴权扩展接口文档(auth_login)
|
|
|
|
在原有登录之上新增两种自定义登录模式,均由 `config.yaml` 的 `auth_login` 段控制。
|
|
|
|
## 配置
|
|
|
|
```yaml
|
|
auth_login:
|
|
# 功能一:用户名直登口令门
|
|
username_login:
|
|
require_password: false # true 时 /login/username 必须带 ?password=
|
|
password: "" # 共享口令;留空默认 123ewq
|
|
# 功能二:token 换登录
|
|
token_login:
|
|
enabled: false # 总开关
|
|
token_info_url: "https://ch1.b.uat.4.cn/consumer/login/getTokenInfo"
|
|
service_authorization: "Bearer admin" # 调上游接口的鉴权头
|
|
timeout_seconds: 10
|
|
verify_ssl: false # 上游 HTTPS 证书校验;UAT/内网自签证书需置 false,生产置 true
|
|
ca_cert_path: "" # 可选:PEM 格式 CA 包路径,设置后优先生效并强制校验
|
|
```
|
|
|
|
> **HTTPS 注意**:`token_info_url` 是 HTTPS。若上游用自签名 / 私有 CA 证书(UAT、内网常见),`verify_ssl: true` 时 httpx 的 TLS 握手会失败,导致 token 登录**恒定 401**。此时应:
|
|
> - 临时/内网:`verify_ssl: false`(跳过证书校验);
|
|
> - 正规做法:把私有 CA 证书导出为 PEM,配 `ca_cert_path: /path/to/ca.pem`(优先于 `verify_ssl`,仍做校验);
|
|
> - 生产对外域名(有效证书):保持 `verify_ssl: true`。
|
|
>
|
|
> 握手失败时后端日志会打印具体异常类型(如 `SSLError`)与当前 `verify` 取值,便于排查。
|
|
|
|
配置模型:`packages/harness/deerflow/config/login_config.py`。修改 `config.yaml` 后无需重启(`get_app_config()` 按 mtime 自动重载)。
|
|
|
|
---
|
|
|
|
## 功能一:用户名直登 + 口令门
|
|
|
|
在原 `POST /api/v1/auth/login/username` 上叠加一个共享口令校验。`require_password=false`(默认)时行为完全不变(免密直登 + 自动注册)。
|
|
|
|
### 请求
|
|
|
|
```
|
|
POST /api/v1/auth/login/username[?password=<共享口令>]
|
|
Content-Type: application/json
|
|
|
|
{ "username": "alice" }
|
|
```
|
|
|
|
- `?password=`:仅当 `require_password=true` 时需要。值需等于 `username_login.password`;该项留空时默认口令为 `123ewq`。
|
|
- 口令门是**单一共享口令**,只决定"放不放行",不影响登录成的是哪个账号。
|
|
- 校验失败按 IP 计入登录限速(5 次/5 分钟锁定),与本地密码登录共用同一限速器。
|
|
|
|
### 响应
|
|
|
|
成功 `200`:
|
|
|
|
```json
|
|
{
|
|
"access_token": "<JWT>",
|
|
"token_type": "bearer",
|
|
"expires_in": 604800,
|
|
"user_id": "<uuid>",
|
|
"email": "alice@cm.com",
|
|
"system_role": "user",
|
|
"needs_setup": false,
|
|
"created": false
|
|
}
|
|
```
|
|
|
|
同时种下 `access_token` HttpOnly Cookie。
|
|
|
|
失败:
|
|
|
|
| 状态码 | 场景 |
|
|
|--------|------|
|
|
| `401` | `require_password=true` 但口令缺失或不匹配 |
|
|
| `429` | 触发登录限速 |
|
|
|
|
### 前端入口
|
|
|
|
访问 `/login/<用户名>?password=<口令>`。[LoginPage.tsx](../../../frontend-web/src/pages/LoginPage.tsx) 从 `?password=` 读取并透传给 [`loginByUsername`](../../../frontend-web/src/core/auth/api.ts)。
|
|
|
|
---
|
|
|
|
## 功能二:token 换登录
|
|
|
|
前端用 URL 把上游 token 传进来,后端调上游接口换出用户名再登录。
|
|
|
|
### 请求
|
|
|
|
```
|
|
POST /api/v1/auth/login/token?token=<上游access_token>
|
|
```
|
|
|
|
后端据此向 `token_info_url` 发起(与下方 curl 对齐):**前端传入的 token 直接拼成 `Authorization: Bearer <token>` 头**,上游从该头读取令牌(不再用 cookie,也不再用静态 `service_authorization`)。
|
|
|
|
```bash
|
|
curl 'https://ch1.b.uat.4.cn/consumer/login/getTokenInfo' \
|
|
-X POST \
|
|
-H 'authorization: Bearer <上游access_token>' \
|
|
-H 'content-type: application/x-www-form-urlencoded'
|
|
```
|
|
|
|
上游返回示例:
|
|
|
|
```json
|
|
{ "state": "200", "msg": "操作成功!", "data": { "username": "b1admin", "...": "..." } }
|
|
```
|
|
|
|
后端取 `data.username` → 经 `_username_to_email` 映射 → 库内查找(含跨域名 local-part 兜底)→ **查不到则自动注册** → 发本系统 JWT 并种 Cookie。
|
|
|
|
### 响应
|
|
|
|
成功 `200`:结构同功能一的 `UsernameLoginResponse`(首次自动注册时 `created=true`)。
|
|
|
|
失败:
|
|
|
|
| 状态码 | 场景 |
|
|
|--------|------|
|
|
| `403` | `token_login.enabled=false` |
|
|
| `401` | 上游调用失败 / HTTP 非 200 / `state != "200"` / 未取到 username |
|
|
| `429` | 触发登录限速 |
|
|
| `500` | `token_info_url` 未配置 |
|
|
|
|
### 前端入口
|
|
|
|
访问 `/login?authToken=<上游token>`(用 `authToken` 而非 `token`,以避开既有的 `tools_token` 参数 `?token=`)。LoginPage 命中 `authToken` 时走 [`loginByToken`](../../../frontend-web/src/core/auth/api.ts),不再调用户名直登。
|
|
|
|
---
|
|
|
|
## 安全说明
|
|
|
|
- 两个端点都在 `auth_middleware._PUBLIC_EXACT_PATHS` 白名单内(免会话鉴权,自身完成鉴权)。
|
|
- 口令门是**最低限度**的共享密钥防护,适合内网/受控环境;非每用户独立密码。
|
|
- token 换登录信任上游 `getTokenInfo` 的鉴权结论,务必保证 `token_info_url` 配置正确且走内网/HTTPS。前端传入的 token 会直接作为 `Authorization: Bearer <token>` 发给上游,因此该 token 必须来自可信入口。(`service_authorization` 配置项已不再参与请求,保留仅为兼容,后续可移除。)
|
|
|
|
## 相关代码
|
|
|
|
- 后端端点 / 助手:`app/gateway/routers/auth.py`(`login_by_username`、`login_by_token`、`_get_or_create_user_by_username`、`_fetch_username_from_token`)
|
|
- 白名单:`app/gateway/auth_middleware.py`
|
|
- 配置模型:`packages/harness/deerflow/config/login_config.py`(挂载于 `AppConfig.auth_login`)
|
|
- 前端:`frontend-web/src/core/auth/api.ts`、`frontend-web/src/pages/LoginPage.tsx`
|
|
- 测试:`tests/test_login_config.py`、`tests/test_auth_login_modes.py`
|