4.5 权限系统与安全边界
4 分钟阅读
原文链接: Capabilities 与 Permissions
4.5 权限系统与安全边界
这一节可能是 Tauri v2 与很多“Web 套壳”框架最大的区别:前端不是默认什么都能用。
三个核心名词
先区分三个容易混淆的词:
| 词 | 类比 | 定义 |
|---|---|---|
| Command | 一个“动作” | Rust 或插件提供的可调用函数 |
| Permission | 一张“通行证” | 是否允许某个命令、某些参数范围 |
| Capability | 一份“门禁名单” | 把一组 Permission 绑定到某个窗口/WebView |
把它们组合起来:哪个窗口,能用哪些命令,参数允许到什么程度。
默认文件的例子
新项目 src-tauri/capabilities/default.json:
| |
含义:
- 这份能力名叫
default; - 它作用在
main窗口; - 它放行了
core:default(核心默认权限集)。
src-tauri/capabilities/ 目录中的能力文件默认都会参与构建。如果你在 tauri.conf.json 的 app.security.capabilities 中显式列出 identifier,则只会启用你列出的那些能力,适合需要精细控制多个配置的场景。
谁默认可用、谁默认不可用?
规则可以记成一句话:
你自己注册的自定义 Rust 命令默认全部窗口可用;核心 API 与插件命令默认关闭,必须用 Permission 显式放行。
更严谨地说:如果一个窗口/WebView 没有匹配任何 capability,它连 IPC 层都无法使用。在“至少匹配一个 capability”的前提下,你通过 invoke_handler 注册的自定义命令默认可用;核心 API 与插件命令则仍需要显式权限。
因此刚建好项目时,你也许能调用 invoke('my_command'),但直接调用 window.setTitle 或文件插件却会被拒绝,直到你在 capabilities 里加上对应权限。
给窗口放行某 API
假设希望 main 窗口能设置窗口标题:
| |
权限标识符常形如 插件名:命令组:动作:
core:event:default:核心事件默认权限;core:window:allow-set-title:允许设置标题;fs:allow-read-text-file:文件插件允许读文本文件;shell:allow-execute:允许执行外部程序。
平台差异:一份能力可以只作用于某些平台
移动端与桌面端能力差异很大,可以加 platforms 数组:
| |
支持的值:linux、macOS、windows、iOS、android。
Scope:给命令再套一层参数限制
仅“允许调用命令”还不够时,Tauri 还提供 Scope(作用域)。例如文件插件允许 read,但你可以进一步限制只能读 $HOME/notes/**:
| |
Scope 分 allow 与 deny,deny 优先于 allow。用它可以做到“能读文件,但读不了密钥目录”。
安全边界能做什么、不能做什么
权限系统能:
- 缩小前端被攻破后的“爆炸半径”;
- 防止不小心暴露系统接口与数据;
- 阻止前端越权调用插件/核心命令。
它不能防:
- Rust 代码本身的漏洞;
- 你写得太宽松的 scope;
- 命令实现里的错误检查;
- 系统 WebView 的 0-day;
- 供应链攻击与开发者电脑被攻破。
因此最佳实践是:
- Rust 端永远校验参数;
- 前端只获取最小必要权限;
- 不在前端存密钥;
- 定时更新依赖。
Brownfield 与 Isolation 两种安全模式
官方还定义了两种 IPC 安全模式:
- Brownfield(默认):前端与 Tauri Core 之间直接走 IPC,最接近浏览器开发体验。
- Isolation:在两者之间插入一个独立、加密的沙箱脚本,先过滤/校验再发给 Core,适合对供应链安全要求极高的应用。
大多数项目先用默认 Brownfield 即可;项目进入严肃安全阶段后再了解 Isolation。
建议阅读顺序
- Capabilities:门禁系统文档;
- Permissions:通行证文档;
- Scope:参数范围文档。
概念学完后,可以进入 第 5 章:跨平台开发与工程布局。