前言¶
DeepSeek Harness(下稱 DSH)的 Web GUI 默認不帶登錄,它假設只有 localhost 上有一個用戶。一旦把服務綁定到 0.0.0.0——用手機訪問、在局域網裏共享、或交給小團隊使用——同一網絡內的任何人都能打開這個頁面:讀到全部會話、消耗你配置的模型 API key、甚至修改 host 設置。
DSH 的理念是「一切皆插件」,這類能力不需要改動本體。下面介紹的 islibaodong/dsh-login 就是這樣一個插件:給 Web GUI 加一道登錄牆、一套多賬戶體系,以及按用戶隔離的會話邊界,把單用戶部署變成可控的多用戶部署。
這是什麼¶
islibaodong/dsh-login 是 DSH Web GUI 的多用戶登錄網關插件,維護者爲 islibaodong,許可證爲 MIT,歸類爲 admin-security。它由三部分能力組成:登錄牆、GUI 內的用戶管理、按用戶的會話與工作區隔離。用戶的添加與管理不需要 CLI,全部在 Web GUI 裏完成。
核心功能¶
登錄牆¶
頁面、靜態資源、SPA 路由、API 與 WebSocket 均要求有效會話,未認證訪問統一重定向到 /login。也就是說,不只是頁面打不開,直接請求 API、建立 WebSocket 同樣被擋住。
多賬戶與用戶管理¶
首次訪問會顯示一次性的「創建管理員賬戶」頁面。之後的新用戶由管理員添加:登錄後進入 設置 → 用戶管理 → 新建用戶。
用戶管理面板提供最近登錄時間、在線會話數,以及重置密碼、禁用、移除三種操作。禁用、移除、改密都會立即吊銷該用戶的在線會話。
dsh-login 自身的設置貢獻已按用戶區分:管理員看到 設置 → 用戶管理,普通用戶看到 賬戶(身份 + 登出)。普通用戶不會調用管理員 API,每個用戶也都能在設置面板裏找到登出入口。
按用戶隔離會話與工作區¶
普通用戶只能看到和操作自己的會話(包括自己創建的 subagents/forks);他人的會話、消息、工作區一律不可見。憑據、host 設置等管理域對普通用戶整體禁止。
管理員是例外:不受隔離,可見全部會話,擁有完整配置權限。
插件還提供 defaultWorkspace:在用戶首次訪問 /api 時爲其自動配置默認工作區。
遠程訪問:Host 白名單自動學習¶
/api 的 host 信任校驗使用一個動態集合:LAN 字面量 + trustedHosts + 自動學習的主機。任何一次成功登錄,其 Host 都會寫入持久化白名單。因此通過 frp、隧道或局域網 IP 訪問 GUI 時,不需要手工編輯 trustedHosts;白名單本身可以在 設置 → 用戶管理 中管理。
能力發現與靜默拒絕¶
兩個配套機制,減少普通用戶瀏覽器裏的無意義報錯:
- 能力發現:
GET /api/auth/capabilities,需會話認證,客戶端據此瞭解當前會話具備哪些能力; - 靜默讀拒絕:無權限的讀探測返回 204 而不是報錯,寫操作仍返回 403,該行爲可通過 quietDenials 開關。
會話持久化¶
登錄會話持久化到 <dataDir>/sessions.json(文件權限 0o600)。進程重啓後已有的 cookie 仍然有效,默認 TTL 爲 7 天;只有真正的登出、密碼修改、用戶移除或 TTL 到期纔會使其失效。
安裝與啓用¶
安裝是一條命令:
dsh plugin --profile web add github:islibaodong/dsh-login
之所以是 --profile web:DSH 按 profile 目錄($DSH_HOME/profiles/<name>)安裝插件,而 web 是啓動 Web GUI 的那個 profile。如果你用的是自定義 profile,把命令裏的 web 換成對應名稱即可。
安裝時,dsh plugin add 會讀取包內聲明的 cordis.patch.yml,自動完成三件事:
1、掛載 dsh-login 插件行;
2、禁用 web-runtime 行(dsh-login 接管 frontend-static 的 fallback 位置,並重新提供 webRuntime 服務);
3、禁用自帶的 connection 行(dsh-login 掛載自己的身份感知接管,並提供 dist/client.js)。
經過上面的步驟,重啓 dsh web 並打開 GUI,首次訪問會出現一次性的「創建管理員賬戶」頁面,設置用戶名與密碼;隨後以管理員身份登錄,在 設置 → 用戶管理 → 新建用戶 中添加其他用戶。
不需要時,卸載同樣是一條命令:
dsh plugin --profile web remove @islibaodong/dsh-login
手動安裝(替代方式)¶
如果你希望自己管理 patch 文件,可以在 profile 的 cordis.patch.yml 中添加 insert 行:
- insert:
- id: dsh-login
name: '@islibaodong/dsh-login'
config:
password: DSH_LOGIN_PASSWORD # 憑據引用名,用戶存儲按 <name>_USERS 命名
distIndex: '' # 留空自動解析前端 dist
dataDir: '' # 留空解析爲 <DSH_HOME>/.dsh-login
sessionTtl: 604800 # 會話 TTL,默認 7 天
autoTrustHosts: true # 成功登錄的 Host 寫入 /api 白名單
enabled: true # 設爲 false 可不卸載直接停用
defaultWorkspace: true # 首次 /api 訪問時自動配置默認工作區
workspaceRoot: '' # 默認工作區的根目錄,留空爲 <DSH_HOME>/workspaces
注意:dsh-login 會接管 fallback 位置並重新提供 webRuntime 服務,所以手動安裝時除了插入上面的行,還需按倉庫 README 的說明禁用 web-runtime 行與自帶 connection 行,其餘組合不受影響。
從舊版單密碼版本升級¶
dsh-login 此前是單密碼版本。從舊版升級後,舊的單密碼不再能登錄任何人,升級後首次訪問會引導創建新的管理員賬戶。
當前狀態:開發已暫停¶
倉庫 README 明確標註:本倉庫的開發已暫停。已交付的功能——登錄牆、多賬戶管理、按用戶隔離、遠程 web-ui 兼容、能力發現、靜默讀拒絕——完整可用。未完成的是按角色控制第三方 UI 插件功能(對無權限用戶隱藏、不渲染、不發請求),這一項被上游 DSH 的能力阻塞,不是本插件單獨能解決的。
具體卡在三處上游限制:
1、DSH 設置面板渲染的是單一全局 section 列表,插件無法在 dsh-login 內按用戶顯示或隱藏設置 section;
2、DSH WebServer 的路由優先級爲 exact-beats-prefix,且沒有 pre-routing hook,自行註冊精確路由的第三方插件(例如 @linxin666/dsh-pet 註冊的 /api/pet/pets、/api/pet/state)無法被 dsh-login 按用戶攔截或靜默;
3、DSH 客戶端運行時會激活所有打包插件,沒有按用戶的激活門檻,未改造的第三方插件仍會對每個用戶觸發掛載期探測。
作者在等待上游 DSH 提供 per-identity 的 slot/section 過濾或條件插件激活;屆時可以在已交付的能力面之上,實現按角色的功能控制。
適用場景與注意事項¶
適合的場景:
- 把 DSH Web GUI 暴露到局域網,多人共用;
- 通過 frp 或隧道從外部訪問自己的 GUI;
- 小團隊共用一套服務,各自維護各自的會話與工作區。
使用前注意:
1、插件以當前 dsh 進程的權限運行,安裝任何第三方插件前都應檢查其源碼與許可證。dsh-login 的許可證爲 MIT,源碼在 GitHub 公開。
2、普通用戶的能力邊界是明確的:可以正常聊天——創建、打開、繼續自己的會話,運行 subagents,管理自己工作區的內容;其餘操作(讀他人會話、憑據、插件/預設/host 設置、模型 key 管理)都會被拒絕。
3、開發已暫停,且按角色的第三方插件功能控制依賴上游進展,選用前請把這兩點納入評估。
小結¶
dsh-login 用一條安裝命令,給 DSH Web GUI 補上了默認缺位的登錄與多用戶能力:登錄牆擋住未認證訪問,管理員在 GUI 內完成賬戶管理,普通用戶之間會話互不可見,重啓後登錄態依然保留。對需要把 GUI 開放到局域網或遠程訪問的使用者,這是補齊這塊短板的直接做法。
- 目錄頁:https://www.skillhub.cn/plugins/islibaodong/dsh-login
- GitHub 倉庫:https://github.com/islibaodong/dsh-login
skillhub.cn 是社區維護的插件目錄,與 DeepSeek、幻方無官方從屬關係。