Tauri 2 多构建变体 ACL 报错:remote.urls 是权限门,不是标签
桌面应用要同时发两个构建变体:一个指向线上域名,一个指向局域网地址。本地开发一切正常,但给 LAN 构建包装好一发,一启动就报:
Command sidecar_call not allowed by ACL
启动页卡死,什么 UI 都不显示。换回 prod 包,同一台机器,同一个代码库,一切正常。
现象
tauriInvoke('sidecar_call', …)在 prod 构建下正常返回- LAN 构建下同样的调用被 ACL 拦截,错误信息
Command sidecar_call not allowed by ACL - 启动时需要 sidecar 的 bootstrap 页面一进入就进
catch,界面一片空白 - 用
RUST_LOG=tauri=debug跑,日志里能看到只有lancapability 对当前窗口生效
根因
Tauri 2 的 capability 文件里,remote.urls 字段是一个源门(origin gate):这份 capability 的所有权限,只在当前 webview 加载的 URL 匹配其中某个 glob 时才激活。
重点:多个 capability 文件的权限不会跨文件自动合并。
典型的误解配置长这样:
// capabilities/default.json
{
"identifier": "default",
"windows": ["main"],
"remote": { "urls": ["https://app.example.com/*"] },
"permissions": [
"core:default",
"shell:allow-execute",
"allow-sidecar-call"
// ...完整权限集
]
}// capabilities/lan.json
{
"identifier": "lan",
"windows": ["main"],
"remote": { "urls": ["http://192.168.x.x/*"] },
"permissions": [
"updater:default" // 只加了一条「看起来 LAN 才需要的」权限
]
}LAN 构建加载的是 http://192.168.x.x,不匹配 default.json 的 remote.urls,所以 default.json 对这个窗口完全无效。allow-sidecar-call 没有被任何激活的 capability 声明,ACL 自然拒绝。
每一个 capability 文件只在其 remote.urls 命中当前 webview 来源时才生效。
不同来源的 capability 之间权限不互通,必须在每个文件里重复声明所有需要的权限。
失败无声——没有「此来源权限不足」的提示,只有 ACL 拒绝指令名称。
正解
方案 A — 在每个来源的 capability 里重复完整权限集(小项目推荐)
把 default.json 里的完整权限列表原封不动复制到 lan.json:
// capabilities/lan.json
{
"$schema": "https://schema.tauri.app/config/2",
"identifier": "lan",
"windows": ["main"],
"remote": { "urls": ["http://192.168.x.x/*"] },
"permissions": [
"core:default",
"core:window:default",
"core:webview:default",
"core:event:default",
"core:app:default",
"updater:default",
"process:default",
"process:allow-restart",
"shell:allow-execute",
"allow-sidecar-call"
]
}方案 B — 拆分「常驻权限」与「来源白名单」(权限集较大时推荐)
新建一个不带 remote.urls 的 capability 文件,只放通用权限;各来源文件只声明 remote.urls,不重复权限列表。没有 remote.urls 的 capability 对所有窗口的本地内容生效,配合来源文件共同覆盖所有场景。
注意:如果 capability 文件是构建脚本从模板渲染生成的(输出文件被
.gitignore), 要改模板,不要直接改生成文件——否则下次构建会被覆盖。
修完之后记得完整重新构建——capability JSON 在构建时编译进二进制,运行时修改磁盘上的文件对已安装的包无效。
用 RUST_LOG=tauri=debug 启动,日志会打印哪些 capability 对当前窗口生效,可以直接验证。
排查备忘
RUST_LOG=tauri=debug启动,搜日志里的capability,确认哪些文件命中了当前窗口- 对比命中的 capability 的
remote.urlsglob 和实际加载的 URL(协议、主机、端口、路径都要精确匹配,大小写敏感) - 检查错误出现的 capability 文件里是否声明了对应的
allow-<command-name>权限
一句话外卖
Tauri 2 的
remote.urls是每个 capability 自己的激活开关,多源应用必须在每个来源的 capability 里重申全量权限,没有「继承」也没有「合并」。