Tauri 的权限模型建立在“默认拒绝”的基础上:所有可能访问系统资源的 API 在启动时都是锁死的,只有你在 tauri.conf.json 的 allowlist 中显式开启的条目才会生效。这种白名单机制让你可以对应用的每一项能力进行精细化控制,既保护用户隐私,又避免被注入的恶意前端脚本利用。
下面按照模块分类,对常见的权限项做深度配置解析。
1. 文件系统(fs)
控制应用对本地文件的读写,以及文件选择对话框的调用。
{
"allowlist": {
"fs": {
"all": false, // 关闭所有 fs API
"readFile": true, // 允许读取文本文件
"writeFile": true, // 允许写入文件
"readDir": true, // 允许列出目录内容
"copyFile": false,
"createDir": false,
"removeDir": false,
"removeFile": false,
"renameFile": false,
"scope": ["$APPDATA/**"] // 限制可访问的目录范围,支持模式匹配
}
}
}
scope是关键安全字段。可以设置为用户数据目录($APPDATA、$HOME等),或应用自身的资源目录,避免任意路径访问。- 如果不指定
scope,前端理论上可以请求任意路径(仍需用户确认或对话框选择),但强烈建议配合dialog权限来限制。
实用提示:文件读写最好结合 dialog 的 open 或 save 使用,让用户显式选择文件,再把路径传给后端,这样能进一步提升安全性。
2. 对话框(dialog)
是否允许打开系统文件选择器、消息框等。
{
"allowlist": {
"dialog": {
"all": false,
"ask": true, // 允许弹出询问对话框
"confirm": true,
"message": true,
"open": true, // 允许打开文件/目录选择器
"save": true // 允许保存文件对话框
}
}
}
- 对话框权限通常和
fs权限配合使用。即使fs开了readFile,如果dialog.open被禁用,用户也无法通过选择文件来指定路径,只能读取应用预定义的固定路径。
3. Shell(shell)
控制是否能在 WebView 中以默认程序打开外部链接、打开文件管理器、执行命令等。
{
"allowlist": {
"shell": {
"all": false,
"open": true, // 允许在浏览器或默认应用中打开 URL/文件路径
"scope": ["https://**", "mailto:**"] // 限制可打开的 URL 协议和域名
}
}
}
open常用于打开外部网页、发送邮件或打开本地文件。通过scope可以精确限制白名单,比如只允许打开公司域名。- 注意:Tauri 1.x 的 shell 模块还支持
execute(执行命令),但出于安全考虑,该功能在后续版本已逐渐被自定义命令取代。建议将任何需要执行外部程序的操作封装为 Rust 命令,而不是直接暴露给前端。
4. HTTP(http)
控制前端是否可以发起跨域或受约束的 HTTP 请求。通常前端本身就可以用 fetch,但 Tauri 也提供了一个额外的 HTTP 客户端(tauri-plugin-http),该模块权限独立。
{
"allowlist": {
"http": {
"all": false,
"request": true,
"scope": ["https://api.example.com/**"] // 只允许访问特定 API 端点
}
}
}
- Tauri 的 HTTP 客户端发起请求时会绕过浏览器的同源策略和 CORS 限制,因此
scope的配置比 Web 更严格,必须精确限定。 - 如果你的应用只是前端
fetch自己的后端 API,通常不需要开启这项权限,直接使用浏览器的fetch即可(受服务端 CORS 配置管控)。
5. 剪贴板(clipboard)
控制读写系统剪贴板。
{
"allowlist": {
"clipboard": {
"all": false,
"readText": true,
"writeText": true
}
}
}
- 剪贴板权限一般不会造成大风险,但出于隐私考虑,部分场景(如企业内网桌面应用)可能只想开启写入,禁止读取用户的剪贴板内容。
6. 全局快捷键(globalShortcut)
控制是否允许注册系统级别的快捷键(即使应用在后台也能响应)。
{
"allowlist": {
"globalShortcut": {
"all": false,
"all": false, // 重复了,需修正
}
}
}
- 正确写法是:
{
"allowlist": {
"globalShortcut": {
"all": false // 禁用所有全局快捷键
}
}
}
- 如果需要注册单个快捷键,只能通过前端调用 API 并在此权限开启的前提下。对于一般桌面工具,建议保持关闭,除非确实需要截图、录音时的全局热键功能。
7. 通知(notification)
控制是否允许发送系统通知。
{
"allowlist": {
"notification": {
"all": true // 完全开启通知
}
}
}
- 通知权限很少需要细粒度限制,通常直接开启即可。注意在 macOS 上,还需要应用具有签名和对应的 entitlement。
8. 窗口与协议(window & protocol)
Tauri 的窗口创建、关闭、大小控制等已有默认的权限边界,一般不需要额外的白名单条目。但如果你需要注册自定义协议(如 myapp://),则需要开启 protocol 权限并进行资产配置,这里不作展开。
深度自定义:命令白名单
除了上述内置模块,当你编写自定义 Rust 命令(用 #[tauri::command] 标记)时,这些命令也是默认拒绝前端调用的。你需要将它们明确添加到 invoke_handler 或构建器配置中:
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
my_custom_command,
another_command
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
只有出现在这个列表里的命令才能被前端通过 invoke 调用,相当于手工维护的第二层白名单。
安全实践总结
- 最小权限原则:只开启应用真正用到的 API 模块,不要直接设置
all: true。 - 使用
scope限制范围:尤其是fs、shell、http等涉及外部资源的模块。 - 前端永远不信任:即使你开启了权限,也可以在 Rust 命令中做第二次验证(例如校验路径、签名令牌等)。
- 审计配置文件:把
tauri.conf.json纳入代码审查流程,任何新增权限都要有充分理由。
通过这种深度可定制、白名单驱动的权限体系,Tauri 让安全性从“说起来重要”变成了“代码级可执行”的实战准则。