Files
zhanlu_proxy/README.md
T
m1saka c3af3caa5b
build / build (push) Successful in 58s
Add admin login session flow
2026-07-09 00:22:27 +08:00

240 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Zhanlu Proxy
一个本地 Go 代理服务,用于读取湛卢插件凭据,按插件认证签名规则请求湛卢上游,并暴露 OpenAI 兼容接口。
当前实现包含:
- 登录页支持插件默认的移动云手机号验证码登录,成功后自动保存凭据到本地 JSON。
- OpenAI 兼容接口:`/v1/models``/v1/chat/completions`
- 湛卢签名逻辑:RSA `authorization`、SHA-256 query hash、HMAC-SHA1 `Signature`
- 湛卢加密 SSE 响应解密并转换为 OpenAI SSE;非流式请求在本地聚合为 OpenAI Chat Completion JSON。
- OpenAI 函数/工具调用:支持 `tools``tool_choice`、流式 `delta.tool_calls`、非流式 `message.tool_calls` 以及 `role: tool` 结果续传。
## 运行
```powershell
go run ./cmd/zhanlu-proxy
```
默认监听:
```text
http://127.0.0.1:8080
```
打开首页会自动跳转到管理登录页:
```text
http://127.0.0.1:8080/
```
## systemd 服务示例
假设二进制文件放在:
```text
/opt/zhanlu-proxy/zhanlu-proxy
```
凭据文件放在:
```text
/opt/zhanlu-proxy/credentials.json
```
创建环境变量文件 `/etc/zhanlu-proxy/zhanlu-proxy.env`
```env
ZHANLU_LISTEN_ADDR=:8080
ZHANLU_CREDENTIALS_FILE=/opt/zhanlu-proxy/credentials.json
ZHANLU_SERVER_BASE_URL=https://api-wuxi-1.cmecloud.cn:8443
ZHANLU_UPSTREAM_PATH=/api/acepilot/zhanlu/aiDeveloper/chat
ZHANLU_MODELS=glm47,minimax-m25
ZHANLU_DEFAULT_MODEL=minimax-m25
ZHANLU_UPSTREAM_TIMEOUT=300s
ZHANLU_LOGIN_PASSWORD=change-this-login-password
OPENAI_COMPAT_API_KEY=change-this-local-secret
```
创建 systemd service 文件 `/etc/systemd/system/zhanlu-proxy.service`
```ini
[Unit]
Description=Zhanlu OpenAI-compatible proxy
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/zhanlu-proxy
EnvironmentFile=/etc/zhanlu-proxy/zhanlu-proxy.env
ExecStart=/opt/zhanlu-proxy/zhanlu-proxy
Restart=always
RestartSec=3
User=zhanlu-proxy
Group=zhanlu-proxy
[Install]
WantedBy=multi-user.target
```
启用并启动服务:
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now zhanlu-proxy
sudo systemctl status zhanlu-proxy
```
查看日志:
```bash
journalctl -u zhanlu-proxy -f
```
## 登录与凭据
### 移动云手机号验证码登录
打开 `/login` 后输入手机号并点击“获取验证码”。实现按插件默认登录分支工作:
如果设置了 `ZHANLU_LOGIN_PASSWORD``/login` 只负责管理密码登录。密码正确后服务会设置 HttpOnly 会话 Cookie,并跳转到 `/admin/login``/admin/login` 才是手机号验证码登录湛卢的页面,之后才能查看凭据状态、获取短信验证码、保存凭据或使用备用 SSO 管理接口。
- 生成 16 位一次性 `secret`
- 使用插件内置 RSA 公钥加密手机号和 `secret`
- 调用公网接口 `/api/query/acepilot-h5/manager/code/getAuthCode` 发送验证码。
- 输入验证码后调用 `/api/query/acepilot-h5/manager/code/checkCode`
- 使用本次 `secret` AES 解密响应中的 `ak``sk``license`,得到 `AccessKey``SecretKey``Token`
- 凭据会写入 JSON 文件,后续 OpenAI 兼容接口自动读取。
默认保存到当前执行目录:
```text
credentials.json
```
可以通过环境变量覆盖:
```powershell
$env:ZHANLU_CREDENTIALS_FILE="E:\path\to\credentials.json"
```
手机号验证码登录使用 `ZHANLU_SERVER_BASE_URL`,默认公网地址来自插件配置:
```powershell
$env:ZHANLU_SERVER_BASE_URL="https://api-wuxi-1.cmecloud.cn:8443"
```
四共 SSO 的 `/auth/start``/auth/callback` 仍保留为备用接口,但不是 `/login` 的默认主流程。
## OpenAI 兼容接口
### 健康检查
```powershell
curl http://127.0.0.1:8080/healthz
```
### 模型列表
```powershell
curl http://127.0.0.1:8080/v1/models
```
### Chat Completions
非流式:
```powershell
curl http://127.0.0.1:8080/v1/chat/completions `
-H "Content-Type: application/json" `
-d '{"model":"minimax-m2.5","messages":[{"role":"user","content":"hello"}],"stream":false}'
```
流式:
```powershell
curl -N http://127.0.0.1:8080/v1/chat/completions `
-H "Content-Type: application/json" `
-d '{"model":"minimax-m2.5","messages":[{"role":"user","content":"hello"}],"stream":true}'
```
### 工具调用
请求中的 `tools``tool_choice` 会传给湛卢模型。流式响应返回增量 `delta.tool_calls`;非流式响应会把分片聚合为完整的 `message.tool_calls`,并保留 `finish_reason: "tool_calls"`。执行工具后,将 assistant 的 `tool_calls``role: "tool"` 结果放回 `messages` 再发起请求即可得到最终回答。
如果设置了本地 OpenAI 兼容 API Key,需要带 `Authorization`
```powershell
$env:OPENAI_COMPAT_API_KEY="local-secret"
```
```powershell
curl http://127.0.0.1:8080/v1/models `
-H "Authorization: Bearer local-secret"
```
## 配置项
| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `ZHANLU_LISTEN_ADDR` | `:8080` | 本地监听地址 |
| `ZHANLU_SERVER_BASE_URL` | `https://api-wuxi-1.cmecloud.cn:8443` | 湛卢上游 Base URL |
| `ZHANLU_UPSTREAM_PATH` | `/api/acepilot/zhanlu/aiDeveloper/chat` | 湛卢聊天接口路径,按插件 `createZhanluRequest` 默认分支设置 |
| `ZHANLU_CREDENTIALS_FILE` | `credentials.json` | 凭据 JSON 路径,默认当前执行目录 |
| `ZHANLU_ACCESS_KEY` | 空 | 直接从环境变量提供 AccessKey |
| `ZHANLU_SECRET_KEY` | 空 | 直接从环境变量提供 SecretKey |
| `ZHANLU_TOKEN` | 空 | 直接从环境变量提供 Token |
| `ZHANLU_SSO_BASE_URL` | `http://rdcloud.4c.hq.cmcc` | 四共 SSO 备用页面 Base URL,非默认手机号登录流程 |
| `ZHANLU_SSO_EXCHANGE_URL` | `https://api-wuxi-1.cmecloud.cn:8443/cmdevops-aiplus-agent-gateway/api/acepilot/zhanlu/checkoutCode` | 四共 SSO code 换 token 的备用接口 |
| `ZHANLU_TOKEN_DECRYPT_KEY` | 空 | 解密四共 SSO 返回 `ak/sk/token` 的 AES key;手机号登录不需要设置 |
| `ZHANLU_PUBLIC_KEY_PEM` | 插件内置签名公钥 | 签名 URL 中 `authorization` 使用的 RSA 公钥,通常不需要设置 |
| `ZHANLU_PHONE_PUBLIC_KEY_PEM` | 插件内置手机号登录公钥 | 手机号验证码登录加密手机号和一次性 secret 使用的 RSA 公钥,通常不需要设置 |
| `ZHANLU_MODELS` | `glm47,minimax-m25` | `/v1/models` 返回的模型列表,逗号分隔 |
| `ZHANLU_DEFAULT_MODEL` | `minimax-m25` | 请求未传 `model` 时使用的默认模型 |
| `ZHANLU_UPSTREAM_TIMEOUT` | `300s` | 上游请求超时 |
| `ZHANLU_STREAM_IDLE_TIMEOUT` | `300s` | 预留的流式空闲超时配置 |
| `ZHANLU_LOGIN_PASSWORD` | 空 | `/login` 管理页面密码;设置后登录成功跳转到 `/admin/login` 管理湛卢凭据 |
| `ZHANLU_DEBUG` | `false` | 调试模式,错误信息更详细但会脱敏敏感 query |
| `OPENAI_COMPAT_API_KEY` | 空 | 本地 OpenAI 兼容接口鉴权 key |
## 凭据优先级
服务启动时按以下优先级加载凭据:
1. 环境变量 `ZHANLU_ACCESS_KEY``ZHANLU_SECRET_KEY``ZHANLU_TOKEN`
2. `ZHANLU_CREDENTIALS_FILE` 指向的 JSON 文件。
登录页面保存后,运行中的服务会立即使用新凭据。
## 安全说明
- `credentials.json` 包含明文 `AccessKey``SecretKey``Token`,请不要提交到仓库。
- 默认保存在当前执行目录的 `credentials.json`
- 建议设置 `ZHANLU_LOGIN_PASSWORD`,避免公网暴露的 `/admin/login` 被直接访问。
- 错误响应默认不会返回签名 URL,避免泄露 `AccessKey``authorization``Signature`
- `ZHANLU_DEBUG=true` 时会返回更详细错误,但仍会对敏感 query 参数脱敏。
## 已知限制
- `ZHANLU_UPSTREAM_PATH` 当前默认值是根据插件分析给出的候选路径,真实环境如果返回 404 或上游错误,需要用实际路径覆盖。
- 手机号验证码接口可能有风控或频率限制;请按正常登录频率使用。
- 湛卢上游必须使用 `stream:true`;代理对 OpenAI `stream:false` 请求负责聚合流式响应。
- UI 模型名 `glm4.7``minimax-m2.5` 会按插件逻辑映射为上游 `glm47``minimax-m25`
- `zhanlu3` 使用独立的内网 VL Gateway 和 `ZHANLU_VL_API_KEY`,当前代理未接入该特殊分支。
## 验证
```powershell
go test ./...
go build ./cmd/zhanlu-proxy
```
本地端点验证:
```powershell
go run ./cmd/zhanlu-proxy
curl http://127.0.0.1:8080/healthz
curl http://127.0.0.1:8080/v1/models
```