中文EN

dsh-auth-gate

security已测通过npmMIT

DSH 网页端登录门插件:账号口令或共享令牌认证、会话 cookie、登录限速,附用户管理 CLI(0.4.1 起声明 dsh.bundle manifest,`dsh plugin add` 一键挂载)。

下载量 / Downloads
4,042
依赖体积 / node_modules
8.67 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

安装

dsh plugin --profile web add dsh-auth-gate

沙箱测试结果

阶段结果
1 安装✓
2 列装✓
3 挂载✓
4 启动—

四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。

README

dsh-auth-gate

[English](README.md) | 简体中文

![npm version](https://www.npmjs.com/package/dsh-auth-gate)

![npm downloads](https://www.npmjs.com/package/dsh-auth-gate)

![npm monthly downloads](https://www.npmjs.com/package/dsh-auth-gate)

![node](https://www.npmjs.com/package/dsh-auth-gate)

![types](https://www.npmjs.com/package/dsh-auth-gate)

![CI](https://github.com/TecFancy/dsh-auth-gate/actions/workflows/ci.yml)

![license](LICENSE)

给 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

链接

GitHub · Homepage · npm

同类插件