Files
deepdata/docs/CASDOOR_SSO_DEPLOYMENT-zh.md
T
figmar 20a1c8b569
CodeQL Advanced / Analyze (actions) (push) Canceled after 0s
CodeQL Advanced / Analyze (java-kotlin) (push) Canceled after 0s
CodeQL Advanced / Analyze (javascript-typescript) (push) Canceled after 0s
CodeQL Advanced / Analyze (python) (push) Canceled after 0s
docs: Casdoor SSO 部署运维手册 + 泛化 E2E 检查脚本(沉淀 31.23 踩坑)
2026-09-01 19:31:08 +08:00

98 lines
5.9 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.
# DeepData × Casdoor SSO 部署运维手册(31.23)
> 适用范围:DeepData(`com.deepdata`)网关单点登录接入自建 Casdoor v2.153.0。
> 生产实例:31.23(Casdoor `:1013`,DeepData 网关 `:8080`,前端/入口 `deepdata.yhdd.apescale.com:1014`)。
> 代码版本:≥ `4e2ec55`(M3:移除 accountOnly,本地登录与 SSO 共存;登录时自动建号,无定时同步)。
## 1. 架构与登录流
```
浏览器 → DeepData 网关 /api/user/oauth/login?next=…
→ 302 Casdoor /login/oauth/authorize(state+next 存 HttpOnly cookie,TTL 300s)
→ Casdoor 登录/同意
→ 回调 /api/user/oauth/callback?code&state
→ 网关换 token → JWKS 验 id_token → upsert 本地用户(自动建号/刷组刷角色)
→ 302 next?sso_token=<本地HS256 JWT>(含 role/groups claims)
→ 前端 callback.html 种 token 进入应用
```
失败时回跳 `next?sso_error=<code>`(`state_mismatch` / `code_exchange` / `id_token_verify` / `internal`)。
角色映射:Casdoor 组 `deepdata-admin|dev|annotator|viewer`(组路径 `datamate/<group>`)→ 本地 `role`,由 `RoleResolver` 按「映射 > 主角色 > defaultRole」解析;组与角色随每次 SSO 登录刷新。
## 2. Casdoor 侧一次性配置(生产现状)
| 对象 | 值 | 说明 |
|------|-----|------|
| 组织 | `admin/built-in`、`admin/datamate` | `password_type=bcrypt` |
| 组(owner=datamate) | `deepdata-admin` `deepdata-dev` `deepdata-annotator` `deepdata-viewer` | 与 casbin 规则对齐 |
| 用户(owner=datamate) | `dmin`(4 组)、`viewer1`(viewer) | **`tag='DeepData'` 必须与应用 tags 一致**;建议给真实 email |
| 证书 | `admin/cert-built-in` | 应用引用用**裸名** `cert-built-in` |
| 应用 | `admin/DataMate` | clientId `144f4d00553aa7db0aab`;tags `["DeepData"]`;tokenFields `["Groups"]`;`redirectUri=https://deepdata.yhdd.apescale.com:1014/api/user/oauth/callback`;**`expire_in_hours ≥ 1`** |
| Casbin | dmin 4 条 / viewer1 1 条 | 角色→组权限 |
### 踩坑清单(均已踩过,排查先对这里)
1. **`expire_in_hours` 必须 ≥ 1**:应用列名是 `expire_in_hours`(double),不是 token_expiration。为 0 时 `expires_in=0`,id_token `exp=iat`,网关验证报 `JWT expired N milliseconds ago`。
`UPDATE application SET expire_in_hours=1 WHERE owner='admin' AND name='DataMate';`
2. **用户 tag 必须在应用 tags 里**:否则 casdoor 登录报 `User's tag: is not listed in the application's tags`。
3. **`/api/login` 收 JSON body**(不是表单):`{"type":"login","application":"DataMate","username":"dmin","password":"…","organization":"datamate","autoSignin":true}`。
4. **`/api/grant-consent` 的 `application` 必须全名** `admin/DataMate`(裸名报 `Invalid application`);session cookie 与登录**同 host**(cookie 域陷阱)。
5. **authorize 无服务端 302**:带 session 的 GET 只返回 SPA 页面,重定向由前端 `grant-consent` 后完成——脚本化验证直接调 `POST /api/grant-consent`。
## 3. DeepData 侧配置
`deployment/docker/deepdata/.env`(compose 注入,变量名映射见 `docker-compose.yml`):
```ini
DEEPDATA_CASDOOR_ENABLED=true
DEEPDATA_CASDOOR_ISSUER=https://sso.yhdd.apescale.com:1014
DEEPDATA_CASDOOR_AUTHORIZE_URI=http://192.168.31.23:1013/login/oauth/authorize
DEEPDATA_CASDOOR_TOKEN_URI=http://192.168.31.23:1013/api/login/oauth/access_token
DEEPDATA_CASDOOR_JWKS_URI=http://192.168.31.23:1013/.well-known/jwks.json
DEEPDATA_CASDOOR_CLIENT_ID=144f4d00553aa7db0aab
DEEPDATA_CASDOOR_CLIENT_SECRET=***
DEEPDATA_CASDOOR_REDIRECT_URI=https://deepdata.yhdd.apescale.com:1014/api/user/oauth/callback
JWT_SECRET=<不变,本地 JWT 签名密钥>
```
> ISSUER 用公网域名(id_token issuer 断言用);三个 URI 用内网直连(网关→casdoor 同机)。
## 4. 构建与部署
```bash
cd /opt/deepdata/deepdata
make gateway-docker-build frontend-docker-build # 产物 deepdata-{gateway,frontend}:latest
cd deployment/docker/deepdata
docker compose up -d --force-recreate deepdata-gateway deepdata-frontend
```
注意:跳板机链路构建长任务易断连,长构建用 `nohup … > /tmp/gw_build.log 2>&1 &` 后台跑再轮询日志。
同步代码到 31.23 **只按文件同步、禁用 `rsync --delete`**,同步后 `git hash-object` 逐文件核对。
## 5. 验证
```bash
GW_BASE=https://deepdata.yhdd.apescale.com:1014 \
CASDOOR_BASE=http://192.168.31.23:1013 \
SSO_CLIENT_ID=144f4d00553aa7db0aab \
LOCAL_ADMIN_PASSWORD=<本地admin密码> \
SSO_TEST_USERS="dmin:<dmin密码>:admin viewer1:<viewer1密码>:viewer" \
bash scripts/casdoor-sso/e2e-check.sh
```
覆盖:配置公开且无 secret 泄漏 → 本地登录(与 SSO 共存)→ SSO 全链路(authorize→登录→consent→callback→sso_token→/me 角色断言)。
网络注意:公网域名经 222.128.20.101 转发到 31.23:1014,**不要用 `--resolve` 把域名指到 192.168.31.23**(该地址本地未监听);E2E 直接访问公网域名即可。
## 6. 排障
| 现象 | 原因 | 处理 |
|------|------|------|
| `sso_error=id_token_verify` + 网关日志 `JWT expired` | 应用 `expire_in_hours=0` | 见 §2 坑 1 |
| `sso_error=internal` + `provision race … reusing existing user` 后 NPE | 本地 email 列 NOT NULL UNIQUE,空 email 互撞(代码已修为空 email 合成 `username@casdoor.local`) | 升级网关镜像;存量行 `UPDATE users SET email=… WHERE email='';` |
| casdoor 登录 `User's tag: is not listed…` | 用户 tag 不在应用 tags | `UPDATE user SET tag='DeepData' WHERE owner='datamate';` |
| grant-consent `Invalid application` | application 用了裸名 | 用 `admin/DataMate` |
| authorize 返回 200 不跳转 | 正常(SPA 行为);若脚本验证用 grant-consent | — |
| `/sso/casdoor/config` `enabled:false` | `DEEPDATA_CASDOOR_ENABLED` 未注入 | 检查 .env + compose 变量名映射 |