首页
/ Hoppscotch 桌面端 Tauri Capabilities 配置解析:为什么 default.json 用通配符匹配 app:// 来源

Hoppscotch 桌面端 Tauri Capabilities 配置解析:为什么 default.json 用通配符匹配 app:// 来源

2026-09-03 21:58:29作者:俞予舒Fleming

本文解读 Hoppscotch 桌面版(基于 Tauri v2)的 Capabilities 权限配置文档 capabilities/README.md。该文档解释了为什么 default.json 中对 windowswebviews 与远端 URL 使用通配符,其根源是「Cloud for Orgs」多租户场景下动态组织域名无法在构建期枚举。读完本文,你能理解 Tauri capability 的安全模型如何与动态 app:// 来源配合,并掌握 app:// 协议沙箱、跨源隔离与 IPC 命令校验这三层安全边界的实现位置。

背景:Tauri v2 的 Capabilities 是什么

Tauri v2 的权限体系由 capability 文件组成,每个 capability 声明「哪些窗口 / Webview / 远端来源」可以使用「哪些权限」。Hoppscotch 桌面端在 src-tauri/capabilities/ 目录下维护了两个 capability:

  • default:面向主窗口和所有 app:// 来源的核心权限集(即本文主角);
  • desktop-capability:跨平台(macOS / Windows / Linux)补充权限,仅包含 updater:defaultwindow-state:default,见 desktop.json

通配符配置长什么样

default.json 的关键片段如下(与文档一致):

{
  "windows": ["*"],
  "webviews": ["*"],
  "remote": {
    "urls": ["app://*"]
  }
}
  • windows: ["*"]webviews: ["*"]:该 capability 不绑定固定的窗口 / Webview 标签名,对任意窗口和 Webview 生效;
  • remote.urls: ["app://*"]:允许任意 app:// 来源的 Webview 发起 IPC 调用。

该 capability 的完整权限清单(同样在 default.json 中)值得逐条了解:

权限 作用
core:defaultcore:window:defaultcore:event:default Tauri 核心事件、窗口管理基础能力
core:window:allow-start-dragging 支持无边框窗口("decorations": false,见 tauri.conf.json)拖拽
core:path:defaultcore:webview:default 路径解析、Webview 操作
core:webview:allow-set-webview-zoom 桌面端缩放(配合 desktop-zoom 类能力)
shell:allow-opendialog:default 打开外部链接、文件对话框
store:default 持久化状态存储
process:defaultupdater:default 进程信息、应用自更新(tauri.conf.json 中 updater 指向 releases 端点并带公钥校验)
fs:allow-* 一组 + fs:scope 文件读写,但 scope 被显式限制在 $APPCONFIG$APPDATA 及其子路径内(default.json
deep-link:default 处理 io.hoppscotch.desktop 深链 scheme
appload:defaultrelay:default 加载本地 Web 应用 bundle、跨进程中继通信

注意这里的对比:文件系统权限用了「最小化 allow 列表 + scope 路径约束」的严格写法,而窗口 / Webview / 远端来源却用了通配符——这正是文档要回答的矛盾点。

为什么必须用通配符:Cloud for Orgs 的动态来源

文档给出的核心理由是多租户(Cloud for Orgs)支持:桌面端允许组织(organization)拥有各自隔离的上下文,隔离手段是动态主机名。当用户切换到组织 acme 时,会新建一个 Webview,其 URL 为 app://acme_hoppscotch_io/。组织名是用户自定义的、构建期不可知,因此无法预先枚举所有窗口标签或 app:// origin。

仓库源码印证了这一机制。在 tauri-plugin-appload/src/commands.rs 中可以看到动态 URL 的构造:

  • 传入 org 时生成 app://{host}/?org={org} 形式的来源,例如 app://test_org_hoppscotch_io
  • 未传入时回退到 app://{sanitized_bundle}/(即固定的 app://hoppscotch/)。

mapping.rs 的注释同样说明:传入自定义 host 后,Webview URL 变为 app://acme_hoppscotch_io/,而普通桌面场景下 Webview URL 恒为 app://{bundle_name}/、主机名不变。guest-js/index.ts 的 API 文档也明确标注该参数「enables cloud-for-orgs support」——即同一个 JS bundle 在不同组织下以不同 origin 加载,让前端 JS 可以从 location 读取当前组织。

由于这些主机名在运行时才确定,capability 只能以 app://* 通配符覆盖它们。

安全边界:通配符为什么不等于失守

文档列出了三层安全论证,均可在仓库中找到对应实现:

  1. app:// 协议是封闭沙箱app:// 协议完全由 tauri-plugin-appload 插件处理,外部网站无法向该命名空间注入内容——只有本地 bundle 缓存中提供的内容可通过 app:// URL 访问。插件实现了完整的 URI 处理器与本地存储层(uri/handler.rsstorage/ 等),因此 app:// 的可达面被收敛到本地 bundle。
  2. 跨源不可互访。每个 app:// origin 相互隔离:app://acme_hoppscotch_io/ 的 Webview 无法读取 app://beta_hoppscotch_io/ 的内容。这是浏览器同源策略在自定义协议上的自然延伸——不同 host 即不同 origin。
  3. IPC 命令自带校验。通配权限只是允许任意 app:// origin「发起」IPC 调用,具体命令自身负责参数校验与授权。此外,CSP 也在 tauri.conf.json 中对 connect-src 做了来源约束(ipc: http://ipc.localhost https://api.hoppscotch.io 等),从网络层再收一道。

还有一个补充事实:README.md 提到,自托管部署下连接自定义域名还需要把对应 app://xxx origin 加入 WHITELISTED_ORIGINS 环境变量——这说明即便 capability 层放行,应用自身仍保留一层 origin 白名单校验,与「命令自身强制授权」的表述互为印证。

曾考虑过的替代方案及其被否原因

文档「Alternatives Considered」一节给出了两条被否决的路径,值得记录以免后人重蹈:

  • 显式模式如 Hoppscotch-*:Tauri 的 capability 系统在多数上下文中不支持对窗口名使用 glob 模式,写死前缀也无法覆盖动态组织主机名;
  • 模式匹配如 app://*_hoppscotch_io:需要长期维护一个「允许的后缀」清单,且无法适配自定义部署(自托管域名各不相同)。

历史演进:从显式窗口名到通配符

文档「Previous Configuration」一节点明,在支持 Cloud for Orgs 之前,capability 使用的是显式窗口名:

{
  "windows": ["main", "Hoppscotch-curr", "Hoppscotch-next"]
}

这种写法更严格,但与动态组织子域名不兼容,因此在引入多租户后改为当前的 ["*"] + remote.urls: ["app://*"] 组合。main 窗口本身仍由 tauri.conf.json 声明为 500×700、无边框、置顶的初始窗口。

小结:这条配置给 Tauri 桌面开发的启示

default.json 的完整写法可以归纳出一种实用模式:当你的 Tauri 应用存在「运行时动态生成的 Webview / 自定义协议来源」时,与其硬编码来源清单(很快就会腐化),不如把通配符的爆炸半径控制在你自己独占的协议命名空间(如 app://)内,并依赖以下纵深防御:协议层沙箱(来源只能是本地 bundle)、浏览器同源策略(origin 隔离)、命令层参数与授权校验、以及应用级 origin 白名单。Hoppscotch 桌面端正是用这套组合,在 app://* 通配的前提下维持了与显式清单相当的实际安全水位。相关实现可进一步阅读 tauri-plugin-apploadtauri-plugin-relay 以及桌面端主 crate src-tauri/src/lib.rs

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384