前言¶
DeepSeek Harness(DSH)的 WebUI 默认在本机或局域网内监听 HTTP 服务。只要知道地址和端口,未登录的访问者同样可以加载页面、调用 /api、建立 WebSocket。对放在公网反代后面、或多人共用同一台机器的场景,这等于把智能体配置、凭证和会话面完全暴露在网络可达范围内。
社区里常见做法是依赖反向代理层的 Basic Auth,或只在防火墙侧收口;它们要么与 DSH 自身的 Host 信任、Cookie 交换机制脱节,要么无法在同一层同时拦住静态资源、插件 bundle 和 RPC。下面介绍 multidsh 维护的 dsh-webui-auth(npm 包 @multidsh/dsh-webui-auth):在插件层对 WebUI 做传输层强制认证,会话落盘,重启进程不丢登录态;本仓库在 npm 包 dsh-webui-auth@0.3.6 基础上合并 0.3.7 补丁,修复 nginx 等反代强制改写 Host 时登录跳转错误的问题。
这是什么¶
dsh-webui-auth 是 DSH 的持久化 WebUI 身份认证插件(组合包 bundle)。在「设置 → 身份认证」或首次访问登录页创建账号密码后,未认证的浏览器无法加载 WebUI 任何资源、调用任何接口或建立任何实时连接;认证在 HTTP/传输层执行,不能靠浏览器开发者工具绕过。
维护与发布:multidsh(GitHub 仓库 multidsh/dsh-webui-auth);上游基于 Yuuz12 的 dsh-webui-auth@0.3.6(MIT),许可证与版权声明原样保留。社区目录分类为 admin-security。当前 npm 版本 0.3.7,零额外 npm 依赖。
核心功能¶
四层路由包装,不改核心源码¶
认证通过运行时包装 webServer 路由实现,不修改 DSH 核心包源码。大致分工如下:
| 层 | 未认证时的行为 |
|---|---|
WebUI 资源(index.html、/assets/*、SPA 路由) |
302 到登录页 |
/plugins/* |
401 |
/api RPC |
401 |
WebSocket(含 /api/remote.mux 等) |
401,拒绝升级 |
插件每次启动会重做路由包装,并用 2s→10s 重扫捕获晚注册路由。若预期路由包装不完整,setup/configure 会拒绝启用认证(fail-closed),宿主日志与设置页同时报错,避免「开了登录却 /api 裸奔」。
同前缀的顶层 exact 路由(例如 client-hmr 的 /plugins/events)也会被纳入包装,避免匿名读取客户端插件图或长期挂着 SSE。
会话与口令¶
会话为服务端会话,持久化到磁盘(sessions.jsonl),重启 DSH 不掉线,到期自动失效。浏览器通过 HttpOnly; SameSite=Lax Cookie(dsh_wua_session)携带,前端 JS 无法读取。修改密码会吊销所有其他会话。
与核心浏览器认证协作¶
DSH 核心 v0.1.2-alpha.2 及以上自带 launch-token 交换的签名 Cookie(dsh-auth-*)。插件登录成功后会引导浏览器到核心的带 token 根 URL 完成 Cookie 交换;/api 在插件会话校验后原样转交核心。浏览器须同时持有插件会话 Cookie 与核心 Cookie。
0.3.7:反代 Host 与登录跳转¶
部分 nginx 部署会 proxy_set_header Host localhost;,旧逻辑会把登录成功后的跳转 authority 退化成 http://localhost/?token=…。0.3.7 构造跳转 authority 时优先采用 X-Forwarded-Host(严格校验为裸 host[:port]),失败才回退到 Host。
部署侧通常还需要:
dsh web --public-url http://web.example.com决定打印/打开的入口地址;- 非回环域名加入信任列表,例如
dsh web --trusted-host web.example.com(等价于client-connection.trustedHosts),否则核心/api与 WebSocket 仍可能按 Host 栅栏拒绝。
WebSocket 在反代/局域网下还需在 DSH 配置里把对外域名加入 client-connection.trustedHosts,否则已登录也可能无法完成 WS 升级。
DSH Desktop 适配¶
桌面端使用独立 profile desktop。插件 0.3.6 起提供「宿主直连信任桥」:对已被核心认证过的回环宿主直连请求放行,并原样处理核心的 token→cookie 交换(303 + Set-Cookie),避免桌面端因 shell 丢弃 set-cookie 而卡在「Desktop Host authentication failed」。桌面端窗口在传输层无法像浏览器一样落插件会话 Cookie,因此采用 UI 级锁(解锁令牌存 sessionStorage / localStorage,语义见 README)。
DSH Desktop 的 dsh-desktop-* URL 标记在登录跳转中可能丢失;0.3.5 起通过 Cookie dsh_wua_desktop 在文档加载前补投带标记的同源 /,逻辑隔离在 lib/desktop-adapter.js。
安装与启用¶
前提:机器上可用 pnpm(Node 自带 corepack 时可执行 corepack enable pnpm)。
Web profile(推荐,npm):
npx @deepseek-ai/dsh plugin --profile web add @multidsh/dsh-webui-auth
Web profile(GitHub 源码):
npx @deepseek-ai/dsh plugin --profile web add github:multidsh/dsh-webui-auth
DSH Desktop:
npx @deepseek-ai/dsh plugin --profile desktop add @multidsh/dsh-webui-auth
安装后无需给核心打补丁、不改 node_modules 里的核心包;重启 DSH 即生效。成功启动时宿主日志应出现 [dsh-webui-auth] started, credentials file: ...;若出现 ROUTE GATE INCOMPLETE,认证不会启用。
手动备用方式:将包目录放入 profiles/web/node_modules/@multidsh/,并在对应 profile 的 cordis.patch.yml 的 insert 列表增加插件行(字段见仓库 README)。
典型用法¶
1、按上一节命令把插件加入 web 或 desktop profile,重启 DSH。
2、浏览器打开 WebUI,按提示在登录页或「设置 → 身份认证」创建账号与密码。
3、若前面有 nginx 反代且改写了 Host,确保配置 X-Forwarded-Host(nginx 常用 proxy_set_header X-Forwarded-Host $host;),并按 README 设置 public-url 与 trusted-host。
4、桌面端安装到 desktop profile 后,日志出现 host carrier bridge active 表示宿主桥就绪;口令管理与审计在设置页仍可用,浏览器访问宿主 WebUI 依旧需要登录。
适用场景与注意¶
适合谁: 需要给 DSH WebUI 加账号口令、且希望未登录时静态资源与 API 一并拒绝的场景;公网或局域网反代部署、以及使用 DSH Desktop 且希望与宿主 Web 认证策略对齐时,README 中的 Host / trustedHosts / Desktop 桥接说明需要一并阅读。
安全与信任: 插件以当前 DSH 进程权限运行,凭证与会话文件位于 DSH 数据目录;安装前应在 GitHub 仓库 查看源码与 MIT 许可证。社区插件目录 skillhub.cn 与 DeepSeek / 幻方无官方从属关系,安装决策以你方环境为准。
反代旧核心: README 提到在 ≤alpha.1 核心下,已认证请求可能以回环形状转交核心,以便反代部署下使用回环钉死的特权 RPC;具体边界以仓库文档为准。
结尾¶
dsh-webui-auth 把 WebUI 认证做成可安装的持久化插件:四层路由闸门、磁盘会话、fail-closed 启用策略,并在 multidsh fork 中补上反代 Host 导致的登录跳转问题,同时覆盖 Desktop 宿主桥与 UI 锁。需要进一步了解版本变更时,可查看仓库 CHANGELOG.md。