dad6e07b738bc05f3564fa1cdb78d24c00623bcf
- 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.
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 默认会带上该头)。
修改密码
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。
更换签名密钥
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— 生成密码哈希与随机密钥的 CLItest.mjs— 单元测试(node test.mjs,覆盖 15 组流程)
Description
DSH web panel password gate plugin: HTTP Basic auth + signed cookie, fail-open
161 KiB
0 Stars
1 Watchers
1 Forks
Languages
JavaScript
100%