- Início
- Plugins
- Melhorias de UI
- dsh-login
dsh-login
ravenli059/dsh-login
Password gate for dsh-web: opening the web port requires a username/password login; account credentials are stored salted+scrypt-hashed and AES-256-GCM encrypted in a local config file under $DSH_HOME. Host-only cordis plugin, no dsh source changes.
Instalar
dsh plugin --profile web add github:ravenli059/dsh-loginREADME
dsh-login — dsh-web 登录插件
给 dsh-web 加一道登录门:打开 dsh-web 的端口时先要输入用户名和密码,验证通过后才
能看到界面。账号信息不落明文:密码用 scrypt(随机盐)哈希,整个凭据文件再用
AES-256-GCM 加密后写入本地配置文件($DSH_HOME/dsh-login.json,默认
~/.dsh/dsh-login.json)。
适合部署于服务器上的dsh-web服务 需要自行架设nginx服务,把服务映射到局域网内使用
- 纯主机侧 Cordis 插件,不修改任何 dsh 源码;
- 通过
dsh plugin以 bundle 方式挂载(dsh.bundle.patch),依赖列表只有cordis/dsh-host-webserver/schemastery三个 peer; - 自带独立 CLI(
dsh-login),不启动 web 也能管理账号。
特性
| 能力 | 说明 |
|---|---|
| 全量请求门禁 | 包住 webserver 的 register / registerUpgrade / registerFallback:SPA 回退、/api 传输、WebSocket/SSE 升级全部先过会话校验 |
| 会话 | 内存会话 + HttpOnly; SameSite=Strict Cookie(默认 24h,可配置);服务重启全员下线 |
| 首启引导 | 没有账号时打开端口显示“创建管理员账号”页(bootstrap),建完即登录 |
| 加密存储 | 凭据文件 AES-256-GCM 加密;密钥来自 DSH_LOGIN_SECRET(64 hex 或口令)→ 密钥文件 $DSH_HOME/dsh-login.key(自动生成)→ 明文模式(警告) |
| 口令安全 | scrypt(N=2^14, r=8, p=1)随机盐哈希,恒时比较;用户名不存在时烧一次假哈希防枚举 |
| 爆破防护 | 每用户名+IP 滑动窗口限速(默认 5 次/30s → 429)+ 失败延时 |
| CLI | status / set-user / remove-user / list-users / reset,运行中改账号会被 mtime 轮询热加载 |
安装(本机 web profile)
# 1) 把本插件加入 web profile(等价于 pnpm add link:... 到 ~/.dsh/profiles/web)
dsh plugin --profile web add link:D:\code\dsh\dsh-login-plugin
# 2) 重启 dsh web
# 下次打开 http://127.0.0.1:3080 会先看到登录页;首次访问创建管理员账号。
仓库内
node_modules是指向~/.dsh/profiles/node_modules的 junction (与 dsh-ssh 等本地开发包的做法一致,测试与link:安装后的模块解析都靠它)。 若把仓库挪到别处,重建 junction:New-Item -ItemType Junction -Path <repo>\node_modules -Target $env:USERPROFILE\.dsh\profiles\node_modules
卸载:dsh plugin --profile web remove dsh-login,重启后端口恢复开放。
首次使用(二选一)
A. 网页引导(默认):打开端口 → “创建管理员账号” → 设置用户名密码 → 自动登录。
B. CLI(适合禁掉网页引导):
# 在运行 dsh web 的机器上执行(无需启动 web)
node D:\code\dsh\dsh-login-plugin\lib\cli.js set-user --user admin
# 输入密码(交互式提示,避免命令行历史残留)
之后把 bootstrap 设为 denied(见下)即可禁止网页自助建号。
配置
在 profile 的用户层给插件行加配置(dsh plugin --profile web add 后会自动把
dsh-login 行插入组合;改配置就编辑 ~/.dsh/profiles/web/cordis.patch.yml 的
- insert: 里那行 dsh-login,或直接读插件的 cordis.patch.yml):
- id: dsh-login
config:
sessionTtlHours: 12 # 会话有效期(小时),默认 24
bootstrap: denied # 禁止网页自助建号,只用 CLI 管账号
maxAttempts: 10 # 爆破限速:10 次/30s
cookieName: dsh_session
loginPath: /login
logoutPath: /logout
storePollMs: 2000 # 检测 CLI 改账号的轮询间隔(0=关闭)
全部配置项(均带默认值):enabled(true)、storeFile($DSH_HOME/dsh-login.json)、
keyFile($DSH_HOME/dsh-login.key)、sessionTtlHours(24)、cookieName、
bootstrap(auto|denied)、maxAttempts(5)、attemptWindowMs(30000)、
failDelayMs(400)、storePollMs(2000)、loginPath(/login)、logoutPath(/logout)。
主密钥优先级:环境变量 DSH_LOGIN_SECRET(64位 hex 原样使用;任意长口令则 scrypt
派生)→ 密钥文件(不存在则自动生成 64 hex,0600)→ 无密钥时降级明文 JSON(仍
scrypt 哈希,插件会打警告)。
登录机制
- 未登录导航请求(
GET/HEAD+Accept: text/html)→ 返回登录页(200); - 未登录其它请求(含对
/api/*的直接访问、静态资源探测)→401JSON; - 未登录 WebSocket/SSE 升级 → 握手直接
401关闭; - 已登录 → 原 handler 照常处理。
- 公开路径(免登录):登录页、退出页、
/api/auth/{login,bootstrap,logout,status}。 - 退出:
POST /api/auth/logout(清 Cookie),或访问/logout页面;会话只存内存, 重启即全部失效。
CLI 参考
dsh-login status
dsh-login set-user --user <name> [--password <p>] # 新建或重置密码
dsh-login remove-user --user <name>
dsh-login list-users
dsh-login reset --yes # 删除凭据文件(全部账号)
测试
node test/unit.test.mjs # 14 项:crypto / store / sessions / 页面
node test/integration.test.mjs # 4 项:真实 webserver + frontend-static + 插件
集成测试覆盖:真实挂载顺序(登录插件最后加载,回退表已注册→原位重包)、反序 (注册期包装)、bootstrap→登录→SPA/API→登出全流程、WebSocket 升级鉴权、密文 存储无明文、CLI 外部改账号被热加载、bootstrap 禁用路径。测试通过 scrypt 实际计算, 运行约 1–2 s。
安全模型(请读)
- 默认只绑 127.0.0.1:登录门禁解决“端口裸奔”,但明文 HTTP 在网络上可被嗅探。
若
--host 0.0.0.0暴露到局域网/公网,请在前面加 TLS 反向代理,并设置 强口令;DSH_LOGIN_SECRET建议放环境变量(环境变量与 web 进程同属一个 用户空间,这是本项目能提供的最高一级的主密钥隔离)。 - 自动生成的密钥文件与凭据文件同目录:防的是“文件被拷贝/误发/备份泄露”这类
意外读取;对能读整个
$DSH_HOME的攻击者,scrypt 哈希才是最后防线。 - 首启引导:零账号时第一个到达的人即可建管理员账号,所以在暴露到不可信网络
之前先用 CLI 建号并设
bootstrap: denied。 - 会话令牌 256 位随机,仅存内存与 HttpOnly Cookie;
SameSite=Strict挡住跨站 请求伪造。若把 GUI 暴露给多用户,请自行评估多账号并发(本插件支持多用户, 会话相互独立)。
目录结构
lib/crypto.js scrypt 哈希/校验、AES-256-GCM、密钥派生
lib/store.js 加密凭据存储(原子写、热重载)
lib/sessions.js 内存会话 + Cookie 工具
lib/login-page.js 登录 / 引导 / 退出页(单文件内联样式脚本)
lib/paths.js $DSH_HOME 与密钥文件解析
lib/index.js 插件本体:门禁包装 + 公开路由
lib/cli.js 账号管理 CLI
test/unit.test.mjs / test/integration.test.mjs
cordis.patch.yml bundle 补丁(把 dsh-login 行插入组合)