dsh-auth-gate
DSH 网页端登录门插件:账号口令或共享令牌认证、会话 cookie、登录限速,附用户管理 CLI(0.4.1 起声明 dsh.bundle manifest,`dsh plugin add` 一键挂载)。
安装
dsh plugin --profile web add dsh-auth-gate
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✓ |
| 2 列装 | ✓ |
| 3 挂载 | ✓ |
| 4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dsh-auth-gate
[English](README.md) | 简体中文







给 DeepSeek Harness(dsh)的网页版加一道登录关卡。把它放在公网上
运行的 dsh 实例前面,任何人在登录之前都碰不到你的 agent、聊天会话和 LLM 凭据。
在 dsh 官方推出认证功能之前,本仓库会一直维护。 dsh 目前还没有内置登录,这个仓库就是用来补上
这个缺口的:我们会跟进 dsh 的新版本(挂载点变化、兼容的版本范围、Linux 与 Windows 双平台 CI)、
修复升级引入的问题,并照常发版。等官方认证落地,我们会给出迁移方案,同时继续支持大家仍在使用的
dsh 版本,不会让任何人留在一个无人维护的 fork 上。
目录
- [它能做什么](#它能做什么)
- [它不做什么](#它不做什么)
- [市场的「会用你的密钥」徽章](#市场的会用你的密钥徽章)
- [快速开始](#快速开始)
- [首次运行](#首次运行)
- [效果预览](#效果预览)
- [配置](#配置)
- [命令行工具](#命令行工具)
- [管理工具:列出用户与重置密码](#管理工具列出用户与重置密码)
- [内置配置技能](#内置配置技能)
- [故障排查](#故障排查)
- [部署](#部署)
- [认证本地代理(可选)](#认证本地代理可选)
- [环境要求](#环境要求)
- [注意事项与局限](#注意事项与局限)
- [开发](#开发)
- [许可证](#许可证)
它能做什么
- 所有请求都要先登录。 每个页面、每个 API 调用、每条 WebSocket 连接都会检查登录态。没有有效
会话的访客会被引导到登录页;API 和脚本请求直接返回 401。唯一的例外是
GET /manifest.webmanifest:浏览器请求 Web App Manifest 时不带凭据,所以只开放这一条路径,
响应里也只有应用名、图标和显示模式。
- 两种登录方式(配置里二选一):
- 密码(推荐):每个管理员使用自己的用户名和密码。
- 令牌:整个实例共用一个密钥。
- 浏览器和脚本都能用。 浏览器走登录页;脚本和 curl 带上
Authorization: Bearer <token>就能
跳过登录页。
- 管理工具。 密码模式下,管理员可以在设置面板的「账号安全」分区里,或通过 HTTP
(GET /auth/users、POST /auth/users/password)列出用户、重置他人口令;重置会吊销该用户已有的
全部会话,并让他在下次登录时先设置新口令,之后才能访问其他任何内容。只有处于正式会话的 admin
才看得到面板里的管理块;管理面不允许重置自己(自己的口令用上方自助表单,忘记了自己的口令才走
CLI)。
- 可选的两步验证(TOTP)。 密码模式下,账号里添加了 TOTP 密钥的用户登录时,除了密码还要输入
验证器应用生成的 6 位验证码(遵循 RFC 6238;配置有 off/optional/required 三档)。
- 默认配置就是安全的。 密码以哈希形式保存;登录有限速,密码连续输错会临时锁定来源地址;会话
cookie 带有安全属性;配置缺失或损坏时直接拒绝访问,而不是悄悄放行。用户名或密码错误时,
登录卡片会重新显示,并带上 Invalid username or password.:用户名保留,密码需要重新输入。
触发锁定后(HTTP 429 + retry-after),同一张登录卡片会显示需要等待的秒数,并提示该限制只
针对当前网络;剩余尝试次数刻意不显示;浏览器启用了 JavaScript 时,刷新页面也不会再额外
消耗一次尝试机会。
它不做什么
先把边界讲清楚,方便你在安装前判断风险(完整清单和背后的机制见
docs/deployed/known-limitations_zh.md):
- 不等于服务器级安全。 操作系统账号和配置文件仍需要你自己看管(
auth/users.yaml和
.credentials.yaml 生成时权限即为 0600);本插件只守住 dsh 的 Web 入口。
- 不是每个改密码入口都会让会话失效。
dsh-auth user disable会阻止该用户今后登录,并吊销其
已签发的会话(默认 5 秒内生效,见 revokeSweepMs);设置面板里的自助改密会吊销该用户的全部
会话,管理员在面板里重置他人口令同样如此;CLI 的 dsh-auth user passwd 只重写存储的密码哈希。
- 不能替代 HTTPS。 配置了
cookieSecure: true,站点就必须通过 https 提供服务。 - 不是完整的身份提供方(IdP)。 没有 OAuth/OIDC,没有自助注册,也没有邮件重置;用户一律由
管理员通过 CLI 创建和管理。
市场的「会用你的密钥」徽章
插件市场的条目会扫描你会安装的那个包,把里面碰到的能力列出来。本插件扫出来的结果是
credentials(会用你的密钥)、network、fs-read、fs-write 和 env,另加一句红线:
_读凭据的同时还能联网_。这是披露,不是判决;对本插件来说它是准确的。下面说明它对应代码里的什么。
- 只有一处读凭据,而且只在令牌模式下发生。
apply()只在mode: "token"时构造令牌
解析器(src/index.ts);密码模式完全不碰凭据服务。令牌模式下,门禁通过
src/token-resolver.ts 里的 credentials.resolve(config.tokenRef) 解析共享密钥,而
tokenRef(默认 DSH_AUTH_TOKEN)是插件唯一会去要的引用;它不会列出、遍历或读取其他凭据。
- 凭据服务是 harness 自己的一层,取值顺序为
$DSH_HOME/.credentials.yaml(创建时权限即为
0600)、进程环境变量、.env 文件。服务缺失或引用解析不出来时,门禁会拒绝所有请求,而不是放行。
- 联网能力来自插件自身的流量:浏览器请求插件自己的端点(登录、用户管理、重置口令),以及
可选的认证本地代理。数据不会发往其他地方。
- 静态扫描说不了的事:它能证明某个能力存在,证明不了某个能力不存在,也读不出意图。
如果你希望实例完全不读凭据,用密码模式即可。
快速开始
装上插件、重启 dsh,然后打开 dsh 启动时打印的那条链接。全新安装的实例还没有任何配置,所以这条链接
会直接进入首次配置向导:整个过程不需要开 shell,也不需要改配置文件。
# 1. 从 npm 装进你的 dsh profile。 # 自 0.4.1 起,包里声明了 dsh.bundle manifest,`dsh plugin add` 会顺带自动注册挂载 # (dsh.profile.bundles),不需要再手动添加挂载行: dsh plugin --profile web add dsh-auth-gate # 2. 重启 dsh,然后打开它启动时打印的链接 # (http://<host>:<port>/?token=<launch token>)。 dsh --profile web
向导给出的选项跟随当前模式:token 模式(出厂默认)生成并保存共享访问令牌,password 模式创建第一个
管理员。新令牌只在结果页显示一次,点一下就能继续进入 dsh。从下次访问起,那条启动链接又只是一条普通 URL:
在登录页用刚设好的令牌或密码登录即可。其余的事(加用户、开 TOTP、改 mode)仍然在 shell 里做:
见 [首次运行](#首次运行)、[配置](#配置) 和 [命令行工具](#命令行工具)。
首次运行
启动链接会不会打开向导,每次请求都会重新判一次,判据只有一个:这个实例配置好了没有?
- 默认模式是
mode: "token"。 没有DSH_AUTH_TOKEN时,未配置的 token 模式实例会拒绝所有人,
所以启动链接是唯一的入口。只有读取成功且值为空才算未配置;credentials 服务缺失或读取抛错,一律按
已配置处理,不会打开向导。password 模式在 users.yaml 缺失或零用户时同理。
?token=是什么。 它是 dsh 自己的启动令牌,dsh 每次启动打印一次,只在这个进程活着的时候有效。
插件把它当成「你能读服务器控制台」的凭证,随后签一张 bootstrap 会话:最长 1 小时,除了插件自己的
/auth/* 页面什么都打不开。
- 向导能改什么。 它生成并保存共享令牌(token 模式)或创建第一个管理员(password 模式),两者一旦
存在,窗口立刻关闭。它改不了 mode、totp、cookieSecure、sessionTtl 和 proxy:这些要改
$DSH_HOME/cordis.patch.yml 再重启 dsh。
- 之后启动链接会怎样。 它不再放你进来,而且要走两跳:门先把请求转到
/auth/bootstrap?token=...,端点判定实例已配置,再回 302 /auth/login?next=%2F。两跳都不下发
cookie、都不放行,所以启动令牌不是第二把钥匙。
- 怎么再打开向导。 删掉已保存的令牌(或者让
users.yaml没有用户),然后重启 dsh。如果 credentials
服务返回的是缓存值,正是这次重启让它看到变化。
效果预览
本节的截图统一使用英文界面:插件自己的面板跟随 GUI 语言,服务端渲染的页面在任何语言下都是
英文,两版 README 因此共用同一套图。
未登录的访客会先看到登录页(登录卡片由插件在服务端渲染,文案固定为英文,与 GUI 语言无关):
账号启用了 TOTP 两步验证时,登录还有第二步:输入验证器应用里的 6 位验证码(先密码,后验证码):
登录后进入你的实例:
在 dsh 0.1.2-alpha 及更高版本上(这些版本的页面带有 launch token 校验),登录会自动跨过这道校验:
登录跳转会先经过一次相对地址 /?token=… 换取 dsh cookie,然后进入 /(细节见
docs/implemented/impl-launch-token-bridge_zh.md)。
设置面板里有一个醒目的「Sign out」(退出登录)按钮,位置在**Settings → General
(设置 → 通用设置)**页最后一行设置项的下方。它是居中、危险色的实心按钮(16px 门形图标加
本地化文字,配色使用主题 token,深浅色自适应);文案跟随 GUI 语言切换,用的就是设置页语言切换
那套机制。点击后执行的仍是原有的原生登出流程 POST /auth/logout?next=/。
已登录的用户还可以在设置面板的「Account security」(账号安全)分区里自助改密码(仅密码模式):
需要填写当前密码和两次新密码,账号绑定了 TOTP 时再加一次验证码。面板标题旁的图标是本插件自己
设计的(16px 描边风格的盾牌加钥匙孔)。
设置导航里那一枚图标同样来自本插件:
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:39,最后更新 2026-11-06