一、为什么需要 Capabilities?
Tauri 应用的前端运行在系统 WebView 中,而后端则是 Rust 编写的原生代码。前端通过 Tauri 提供的 API 与后端通信,从而访问文件系统、窗口管理、系统托盘等原生能力。
问题在于:如果前端代码被攻破(比如 XSS 攻击),攻击者就可能利用这些 API 对用户系统造成危害。Capabilities 系统正是为了应对这类场景而设计的------它让开发者可以精确控制每个窗口或 WebView 能使用哪些权限,将"最小权限原则"落到实处。
二、核心概念
Capabilities 本质上是一组声明式的权限配置,用来定义哪些窗口(window)或 WebView 被授予或拒绝了哪些权限。几个关键特性值得注意:
- 一个 Capability 可以同时作用于多个窗口或 WebView。
- 一个窗口也可以被多个 Capability 引用。当窗口属于多个 Capability 时,所有相关 Capability 的权限会合并生效------这意味着安全边界会扩大,配置时需要格外小心。
三、配置方式
Capability 文件以 JSON 或 TOML 格式存放在 src-tauri/capabilities 目录下。Tauri 提供了两种主要的配置方式。
方式一:独立文件 + 引用标识符
这是推荐的做法。在 capabilities 目录下定义独立的 Capability 文件,然后在 tauri.conf.json 中通过标识符引用它们。
首先,定义一个 Capability 文件:
bash
// src-tauri/capabilities/default.json
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "main-capability",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"core:path:default",
"core:event:default",
"core:window:default",
"core:app:default",
"core:resources:default",
"core:menu:default",
"core:tray:default",
"core:window:allow-set-title"
]
}
然后在配置文件中引用:
json
// src-tauri/tauri.conf.json
{
"app": {
"security": {
"capabilities": ["my-capability", "main-capability"]
}
}
}
这种方式的好处是保持 tauri.conf.json 的简洁,同时让权限配置模块化、易于维护。
方式二:内联定义
对于简单场景,也可以直接在 tauri.conf.json 中内联定义 Capability,甚至将内联定义和引用混合使用:
json
{
"app": {
"security": {
"capabilities": [
{
"identifier": "my-capability",
"description": "My application capability used for all windows",
"windows": ["*"],
"permissions": ["fs:default", "allow-home-read-extended"]
},
"my-second-capability"
]
}
}
}
需要注意的是,capabilities 目录下的所有 Capability 文件默认自动启用。但一旦在 tauri.conf.json 中显式指定了 Capability,就只有被指定的那些会生效。
四、自定义命令的权限控制
默认情况下,通过 tauri::Builder::invoke_handler 注册的所有命令对所有窗口开放。如果你希望更精细地控制,可以在 build.rs 中使用 AppManifest::commands 来声明:
css
// src-tauri/build.rs
fn main() {
tauri_build::try_build(
tauri_build::Attributes::new()
.app_manifest(
tauri_build::AppManifest::new()
.commands(&["your_command"])
),
)
.unwrap();
}
五、平台特定配置
Capabilities 支持通过 platforms 字段限定作用的目标平台。可选值包括 linux、macOS、windows、iOS 和 android。
一个面向桌面端的配置示例:
bash
// src-tauri/capabilities/desktop.json
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "desktop-capability",
"windows": ["main"],
"platforms": ["linux", "macOS", "windows"],
"permissions": ["global-shortcut:allow-register"]
}
以及面向移动端的配置:
bash
// src-tauri/capabilities/mobile.json
{
"$schema": "../gen/schemas/mobile-schema.json",
"identifier": "mobile-capability",
"windows": ["main"],
"platforms": ["iOS", "android"],
"permissions": [
"nfc:allow-scan",
"biometric:allow-authenticate",
"barcode-scanner:allow-scan"
]
}
这种设计让你可以为不同平台启用不同的插件能力,同时避免在不支持某些硬件的平台上引入无意义的权限。
六、远程 API 访问
默认情况下,Tauri API 只对随应用打包的本地代码开放。但在某些场景下,你可能需要让远程加载的页面也能调用部分 Tauri 命令。这可以通过 remote 配置实现:
bash
// src-tauri/capabilities/remote-tags.json
{
"$schema": "../gen/schemas/remote-schema.json",
"identifier": "remote-tag-capability",
"windows": ["main"],
"remote": {
"urls": ["https://*.tauri.app"]
},
"platforms": ["iOS", "android"],
"permissions": ["nfc:allow-scan", "barcode-scanner:allow-scan"]
}
这里有一个重要的安全提示 :在 Linux 和 Android 上,Tauri 无法区分来自嵌入式 <iframe> 的请求和窗口本身的请求。因此在使用远程 API 访问功能时,务必仔细评估安全影响。
七、安全边界:能做什么,不能做什么
理解 Capabilities 系统的安全边界至关重要。
它能防护的场景包括:最小化前端被攻破后的影响、防止或减少本地系统接口和数据的意外暴露、防止从前端到后端/系统的权限提升。
它无法防护的场景包括:恶意或不安全的 Rust 后端代码、过于宽松的 scope 配置、命令实现中未正确检查 scope、来自 Rust 代码的故意绕过、系统 WebView 的零日漏洞、供应链攻击或开发者环境被入侵。
另外,安全边界依赖于窗口的 label(标签),而非 title(标题)。建议只对高权限窗口开放窗口创建功能。
八、Schema 文件与 IDE 支持
Tauri 通过 tauri-build 自动生成 JSON Schema 文件,其中包含了应用可用的所有权限定义。在 Capability 配置文件中设置 $schema 属性后,你的 IDE 就能提供自动补全,大幅提升开发体验:
bash
{
"$schema": "../gen/schemas/desktop-schema.json"
}
Schema 文件位于 gen/schemas 目录下,通常使用 desktop-schema.json 或 mobile-schema.json,也可以为特定平台定义专属的 Schema。
九、项目结构概览
一个典型的 Tauri 应用目录结构如下:
css
tauri-app
├── index.html
├── package.json
├── src/
├── src-tauri/
│ ├── Cargo.toml
│ ├── capabilities/
│ │ └── <identifier>.json/toml
│ ├── src/
│ └── tauri.conf.json
capabilities 目录存放所有的权限配置文件,每个文件以其 identifier 命名,职责清晰,便于团队协作和代码审查。
十、最佳实践总结
在实际项目中使用 Capabilities 系统时,有几条经验值得参考。首先,遵循最小权限原则,只为每个窗口授予它实际需要的权限。其次,善用独立文件管理------将 Capability 定义为独立文件,通过标识符引用,保持配置清晰。第三,谨慎处理多 Capability 窗口,因为权限会合并,可能意外扩大安全边界。第四,利用平台特定配置,避免在不适用的平台上暴露无意义的权限。最后,对远程 API 访问保持警惕,仔细评估安全影响,尤其是在 Linux 和 Android 上。
Tauri 的 Capabilities 系统体现了"安全默认"的设计哲学------默认情况下,前端的能力是受限的,开发者需要显式地授予权限。这种设计虽然增加了一些配置工作,但换来的是更可控、更安全的应用架构。对于任何关注用户安全的桌面/移动应用项目来说,花时间理解和正确配置这套系统,都是值得的。