Files
panel-auth/README.md
T
dsh dad6e07b73 feat: styled login page + structured JSONL audit logging
- Browser navigation now gets a self-contained login page (no JS, CSP
  hardened, XSS-escaped, cross-origin POST rejected) instead of the native
  Basic dialog; API clients keep 401 + WWW-Authenticate.
- Login/logout endpoints (/panel-auth/login, /panel-auth/logout) issue and
  revoke the signed cookie, then 303 back to the original target.
- Structured audit log (login-ok/login-fail/logout/challenge/reject with
  username, IP, UA, reason), default $DSH_HOME/panel-auth-audit.jsonl,
  5MB rotation; X-Forwarded-For honored behind the reverse proxy.
- Function-plugin form, per-request config, fail-open when unconfigured.
- Tests extended to 15 flows including login page, login POST, logout,
  audit assertions and XSS escaping.
2026-08-16 01:32:37 -04:00

73 lines
3.2 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.
# panel-auth — DSH 面板访问密码插件
`dsh web` 面板加一层原生 HTTP 认证(自绘登录页 + Basic + 签名 Cookie),
挂载在 `/root/.dsh/profiles/web/cordis.patch.yml` 的用户补丁层,升级 DSH 不会丢。
## 认证逻辑
- 浏览器访问(`Accept: text/html`):匿名时返回**内置登录页**(无 JS、CSP 收紧),
表单 POST 到 `/panel-auth/login`,成功后签发 Cookie 并跳回原目标地址。
- API / 脚本(fetch、curl 等):保持经典 `401 + WWW-Authenticate: Basic` 契约,
仍可用 Basic 凭据直接调用,成功后同样签发 Cookie。
- WebSocket 升级:匿名一律 `401`,带 Cookie 放行(浏览器对 WS 不保证携带
Authorization 头,因此依赖 Cookie)。
- `/panel-auth/logout`:清除 Cookie 并回到登录页。
- Cookie 默认 30 天(`cookieTtlSeconds`),HttpOnly + SameSite=Lax。
- **Fail-open**`users` 为空或 `secret` 缺失/过短时不拦截任何请求,
配置写错不会把面板锁死。配置每次请求实时读取,改密码热生效。
## 登录日志(审计)
- 所有登录活动写入结构化 JSONL 文件,默认
`/root/.dsh/panel-auth-audit.jsonl`(可用 `auditLogPath` 配置修改)。
- 事件类型:
| event | 含义 |
| --- | --- |
| `login-ok` | 登录成功(含用户名、IP、User-Agent |
| `login-fail` | 登录失败(含用户名、IP、UA、`reason``bad-credentials` / `missing-fields` / `cross-origin` / `body-too-large` |
| `logout` | 主动登出 |
| `challenge` | 匿名浏览器导航被重定向到登录页 |
| `reject` | 匿名 API / WebSocket 请求被拒绝(含方法、路径) |
- 每条含 `ts`ISO 时间)、`ip`(优先 `X-Forwarded-For`,见下)、`ua`
- 文件超过 5MB 自动轮转为 `<path>.1`
- 查看示例:`tail -f /root/.dsh/panel-auth-audit.jsonl | jq .`
> IP 说明:面板经 Caddy 反代时,直连 socket 是回环地址;插件在检测到回环
> 来源时会取 `X-Forwarded-For` 的首个值作为真实 IP(Caddy 默认会带上该头)。
## 修改密码
```bash
cd /root/.dsh/profiles/web/panel-auth
node hash.js admin 新密码 # 输出新 passwordHash
```
把输出的 `passwordHash` 替换进 `../cordis.patch.yml` 后(loader HMR 热应用;
如未生效则 `systemctl restart dsh-web`)。
## 新增用户
`cordis.patch.yml``users` 列表里再加一组 `username`/`passwordHash`
## 更换签名密钥
```bash
node hash.js --secret # 生成新 secret
```
替换 `cordis.patch.yml``secret` 后重启。注意:更换密钥会使所有已签发
Cookie 立即失效,所有人需重新登录。
## 应急解锁(忘记密码时)
编辑 `/root/.dsh/profiles/web/cordis.patch.yml`
- 临时把 `users` 置为 `[]`(fail-open,面板恢复无密码状态),或
- 用上面的命令生成新哈希替换。
## 文件
- `index.js` — 插件本体(登录页、认证守卫、审计日志、webServer 包装)
- `crypto.js` — scrypt 哈希 / HMAC Cookie 签名(无依赖,纯 node:crypto
- `hash.js` — 生成密码哈希与随机密钥的 CLI
- `test.mjs` — 单元测试(`node test.mjs`,覆盖 15 组流程)