关于 configuring-tauri-scopes
面向 Tauri v2 开发者的范围配置技能,介绍如何通过能力文件为文件系统、HTTP 和命令设置细粒度访问边界,并管理运行时范围。
主要功能
- 01配置文件路径允许与拒绝规则
- 02使用 Glob 模式匹配路径
- 03按 URL 限制 HTTP 访问
- 04通过 Rust 在运行时调整范围
适用场景
- 01仅允许应用访问指定目录
- 02阻止访问敏感文件夹
- 03限制应用可请求的 API 地址
- 04根据验证后的路径扩展访问范围
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ dchuk/ claude-code-tauri-skills --skill configuring-tauri-scopes安装后在 Claude Code 中输入/configuring-tauri-scopes确认已加载。
详细介绍
Tauri 命令作用域
本技能介绍如何在 Tauri v2 应用中配置作用域,以精细控制对命令和资源的访问。
什么是作用域?
作用域是 Tauri 中的一种细粒度授权机制,用于控制命令可以执行哪些特定操作。相比基本的命令访问权限,作用域提供了更精细的权限边界。
主要特征
- 允许作用域:明确允许某些操作
- 拒绝作用域:明确限制某些操作
- 拒绝优先:两者同时存在时,拒绝规则始终优先
- 命令职责:命令实现必须验证并强制执行作用域限制
作用域的工作方式
执行期间,作用域会传递给命令。命令实现负责根据作用域进行验证并强制执行限制。这意味着开发者必须谨慎实现作用域验证,以防止绕过限制。
作用域配置位置
作用域配置在以下能力文件中:
src-tauri/capabilities/default.json(主要文件)src-tauri/capabilities/*.json(其他能力文件)
文件系统作用域
文件系统插件使用兼容 glob 的路径模式来定义可访问的路径。
基本文件系统作用域配置
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Default capability for the application",
"windows": ["main"],
"permissions": [
{
"identifier": "fs:scope",
"allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }]
}
]
}
特定命令的作用域
限制单个文件系统操作,而非全局访问:
{
"permissions": [
{
"identifier": "fs:allow-read-text-file",
"allow": [{ "path": "$DOCUMENT/**" }]
},
{
"identifier": "fs:allow-write-text-file",
"allow": [{ "path": "$HOME/notes.txt" }]
}
]
}
组合使用允许和拒绝作用域
{
"permissions": [
{
"identifier": "fs:allow-rename",
"allow": [{ "path": "$HOME/**" }],
"deny": [{ "path": "$HOME/.config/**" }]
}
]
}
可用路径变量
Tauri 提供了运行时注入的变量,用于表示常见系统目录:
| 变量 | 描述 |
|---|---|
$APPCONFIG | 应用配置目录 |
$APPDATA | 应用数据目录 |
$APPLOCALDATA | 应用本地数据目录 |
$APPCACHE | 应用缓存目录 |
$APPLOG | 应用日志目录 |
$AUDIO | 用户音频目录 |
$CACHE | 系统缓存目录 |
$CONFIG | 系统配置目录 |
$DATA | 系统数据目录 |
$DESKTOP | 用户桌面目录 |
$DOCUMENT | 用户文档目录 |
$DOWNLOAD | 用户下载目录 |
$EXE | 应用可执行文件目录 |
$HOME | 用户主目录 |
$PICTURE | 用户图片目录 |
$PUBLIC | 公共目录 |
$RESOURCE | 应用资源目录 |
$TEMP | 临时目录 |
$VIDEO | 用户视频目录 |
作用域模式
作用域支持 glob 模式,可灵活匹配路径。
模式示例
{
"permissions": [
{
"identifier": "fs:scope",
"allow": [
{ "path": "$APPDATA/databases/*" },
{ "path": "$DOCUMENT/**/*.txt" },
{ "path": "$HOME/project/src/**" }
],
"deny": [
{ "path": "$HOME/.ssh/**" },
{ "path": "$HOME/.gnupg/**" }
]
}
]
}
模式语法
| 模式 | 含义 |
|---|---|
* | 匹配除路径分隔符以外的任意字符 |
** | 匹配包括路径分隔符在内的任意字符(递归) |
? | 匹配单个字符 |
[abc] | 匹配方括号中的任意字符 |
路径遍历防护
Tauri 会阻止路径遍历攻击。以下路径不允许使用:
/usr/path/to/../file../path/to/file
HTTP 插件作用域
HTTP 插件使用 URL 模式来控制网络访问。
URL 作用域配置
{
"permissions": [
{
"identifier": "http:default",
"allow": [{ "url": "https://*.tauri.app" }],
"deny": [{ "url": "https://private.tauri.app" }]
}
]
}
URL 模式示例
{
"permissions": [
{
"identifier": "http:default",
"allow": [
{ "url": "https://api.example.com/*" },
{ "url": "https://*.cdn.example.com/**" }
]
}
]
}
使用作用域定义自定义权限(TOML)
对于插件或自定义命令,可在 TOML 文件中定义权限。
带作用域的基本权限
# permissions/my-permission.toml
[[permission]]
identifier = "scope-appdata-recursive"
description = "Recursive access to APPDATA folder"
[[permission.scope.allow]]
path = "$APPDATA/**"
带拒绝作用域的权限
[[permission]]
identifier = "deny-sensitive-data"
description = "Denies access to sensitive directories"
platforms = ["linux", "macos"]
[[permission.scope.deny]]
path = "$HOME/.ssh/**"
[[permission.scope.deny]]
path = "$HOME/.gnupg/**"
权限集
将权限组合成可复用的集合:
[[set]]
identifier = "safe-appdata-access"
description = "Allows APPDATA access while denying sensitive folders"
permissions = ["scope-appdata-recursive", "deny-sensitive-data"]
动态作用域(运行时管理)
Tauri 支持使用 Rust 的 FsExt 特征在运行时修改作用域。
基本的运行时作用域扩展
use tauri_plugin_fs::FsExt;
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_fs::init())
.setup(|app| {
let scope = app.fs_scope();
// Allow a specific directory (non-recursive)
scope.allow_directory("/path/to/directory", false)?;
// Check what's currently allowed
dbg!(scope.allowed());
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
用于扩展作用域的 Tauri 命令
use tauri_plugin_fs::FsExt;
#[tauri::command]
fn expand_scope(
app_handle: tauri::AppHandle,
folder_path: std::path::PathBuf
) -> Result<(), String> {
// Verify path before expanding scope
if !folder_path.exists() {
return Err("Path does not exist".to_string());
}
// true = allow inner directories recursively
app_handle
.fs_scope()
.allow_directory(&folder_path, true)
.map_err(|err| err.to_string())
}
允许访问特定文件
#[tauri::command]
fn allow_file(
app_handle: tauri::AppHandle,
file_path: std::path::PathBuf
) -> Result<(), String> {
app_handle
.fs_scope()
.allow_file(&file_path)
.map_err(|err| err.to_string())
}
安全警告
应谨慎使用动态作用域扩展:
- 扩展作用域前验证路径
- 尽可能优先使用静态配置
- 绝不要根据未经验证的用户输入扩展作用域
远程 URL 作用域(能力)
控制哪些远程 URL 可以访问应用的命令。
{
"identifier": "remote-api-access",
"description": "Allow remote access from specific domains",
"windows": ["main"],
"remote": {
"urls": ["https://*.mydomain.dev", "https://app.example.com"]
},
"permissions": ["core:default"]
}
完整能力文件示例
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Default capability for desktop application",
"windows": ["main", "settings"],
"platforms": ["linux", "macos", "windows"],
"permissions": [
"core:default",
"core:window:allow-set-title",
{
"identifier": "fs:default"
},
{
"identifier": "fs:allow-read-text-file",
"allow": [
{ "path": "$DOCUMENT/**/*.md" },
{ "path": "$DOCUMENT/**/*.txt" }
]
},
{
"identifier": "fs:allow-write-text-file",
"allow": [{ "path": "$APPDATA/notes/**" }],
"deny": [{ "path": "$APPDATA/notes/.secret/**" }]
},
{
"identifier": "http:default",
"allow": [{ "url": "https://api.example.com/*" }]
}
]
}
安全最佳实践
- 尽量缩小范围:只允许绝对必要的路径和 URL
- 使用拒绝规则:即使在允许的路径中,也要明确屏蔽敏感目录
- 优先使用命令专属范围:使用
fs:allow-read-text-file,而非全局fs:scope - 验证动态范围:运行时扩展范围前,务必验证路径
- 审计范围强制执行:命令开发者必须实现适当的范围验证
- 使用路径变量:为提高可移植性,优先使用
$APPDATA,而非硬编码路径
常见范围模式
只读应用数据
{
"permissions": [
{
"identifier": "fs:allow-read-text-file",
"allow": [{ "path": "$APPDATA/**" }]
},
{
"identifier": "fs:allow-exists",
"allow": [{ "path": "$APPDATA/**" }]
}
]
}
用户文档访问
{
"permissions": [
{
"identifier": "fs:scope",
"allow": [{ "path": "$DOCUMENT/**" }],
"deny": [
{ "path": "$DOCUMENT/.hidden/**" },
{ "path": "$DOCUMENT/**/*.key" }
]
}
]
}
仅限 API 的 HTTP 访问
{
"permissions": [
{
"identifier": "http:default",
"allow": [
{ "url": "https://api.myapp.com/v1/*" },
{ "url": "https://cdn.myapp.com/**" }
],
"deny": [
{ "url": "https://api.myapp.com/v1/admin/*" }
]
}
]
}
故障排除
“路径不在配置的范围内”
此错误表示请求的路径超出了配置范围。解决方法:
- 将路径添加到 capability 的允许列表中
- 检查路径变量是否有拼写错误
- 确认 glob 模式与预期路径匹配
- 检查是否有拒绝规则屏蔽了该路径
测试范围配置
在开发模式下运行以测试权限:
pnpm tauri dev
# or
cargo tauri dev
控制台中会显示权限错误,指出需要配置哪些权限。
参考资料
评论
支持 Markdown