人人都会AI编程

21.2 权限白名单深度配置

更新时间:2026-07-11

Tauri 的权限模型建立在“默认拒绝”的基础上:所有可能访问系统资源的 API 在启动时都是锁死的,只有你在 tauri.conf.jsonallowlist 中显式开启的条目才会生效。这种白名单机制让你可以对应用的每一项能力进行精细化控制,既保护用户隐私,又避免被注入的恶意前端脚本利用。

下面按照模块分类,对常见的权限项做深度配置解析。


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 权限来限制。

实用提示:文件读写最好结合 dialogopensave 使用,让用户显式选择文件,再把路径传给后端,这样能进一步提升安全性。


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 限制范围:尤其是 fsshellhttp 等涉及外部资源的模块。
  • 前端永远不信任:即使你开启了权限,也可以在 Rust 命令中做第二次验证(例如校验路径、签名令牌等)。
  • 审计配置文件:把 tauri.conf.json 纳入代码审查流程,任何新增权限都要有充分理由。

通过这种深度可定制、白名单驱动的权限体系,Tauri 让安全性从“说起来重要”变成了“代码级可执行”的实战准则。