安全架构 #

一、安全模型概述 #

1.1 安全设计原则 #

Tauri 的安全设计遵循以下原则:

原则 说明
最小权限 只授予必要的权限
深度防御 多层安全防护
安全默认 默认配置是安全的
隔离运行 前后端隔离

1.2 安全架构 #

text
┌─────────────────────────────────────────────────────────────┐
│                      安全架构                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    前端 (WebView)                    │   │
│  │  ┌─────────────────────────────────────────────┐   │   │
│  │  │              沙箱环境                        │   │   │
│  │  │  - 无直接文件系统访问                        │   │   │
│  │  │  - 无直接系统 API 访问                       │   │   │
│  │  │  - 受 CSP 策略限制                          │   │   │
│  │  └─────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                            │                                │
│                            │ IPC(受控通道)                 │
│                            ▼                                │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    后端 (Rust)                       │   │
│  │  ┌─────────────────────────────────────────────┐   │   │
│  │  │              权限检查                        │   │   │
│  │  │  - 命令白名单                               │   │   │
│  │  │  - 权限验证                                 │   │   │
│  │  │  - 资源访问控制                             │   │   │
│  │  └─────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

二、安全边界 #

2.1 进程隔离 #

text
┌─────────────────┐     IPC      ┌─────────────────┐
│   WebView       │◄────────────►│   Rust Core     │
│   (沙箱)        │   受控通信    │   (权限控制)    │
└─────────────────┘              └─────────────────┘

2.2 上下文隔离 #

typescript
// WebView 中无法直接访问 Node.js/Rust
// 必须通过 IPC 通道

// ❌ 不可能直接访问
// const fs = require('fs');

// ✅ 通过 IPC 调用
import { invoke } from '@tauri-apps/api/core';
const content = await invoke('read_file', { path: '/path/to/file' });

2.3 预加载脚本安全 #

javascript
// preload.js
const { contextBridge, ipcRenderer } = require('electron');

// 只暴露白名单内的 API
contextBridge.exposeInMainWorld('myAPI', {
    readFile: (path) => ipcRenderer.invoke('read-file', path),
    writeFile: (path, content) => ipcRenderer.invoke('write-file', path, content),
});

三、权限系统 #

3.1 权限配置 #

json
// src-tauri/capabilities/default.json
{
    "$schema": "https://schema.tauri.app/config/2/capability",
    "identifier": "default",
    "description": "Default capabilities",
    "windows": ["main"],
    "permissions": [
        "core:default",
        "shell:allow-open",
        "dialog:allow-open",
        "fs:allow-read-text-file",
        "fs:allow-write-text-file"
    ]
}

3.2 权限粒度 #

json
{
    "permissions": [
        "fs:default",
        "fs:allow-read-text-file",
        "fs:allow-write-text-file",
        "fs:deny-read-dir"
    ]
}

3.3 条件权限 #

json
{
    "permissions": [
        {
            "identifier": "fs:allow-read-text-file",
            "allow": [
                { "path": "$APPDATA/**" },
                { "path": "$DOCUMENT/**" }
            ]
        }
    ]
}

四、CSP 配置 #

4.1 内容安全策略 #

json
// tauri.conf.json
{
    "app": {
        "security": {
            "csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
        }
    }
}

4.2 CSP 指令详解 #

text
default-src 'self'          默认只加载同源资源
script-src 'self'           脚本只从同源加载
style-src 'self' 'unsafe-inline'  样式允许内联
img-src 'self' data: https: 图片允许同源、data 和 https
font-src 'self' https://fonts.gstatic.com  字体允许指定源
connect-src 'self' https://api.example.com  连接允许指定源

4.3 严格 CSP 示例 #

json
{
    "csp": "default-src 'self'; " +
           "script-src 'self'; " +
           "style-src 'self'; " +
           "img-src 'self' data:; " +
           "font-src 'self'; " +
           "connect-src 'self'; " +
           "frame-ancestors 'none'; " +
           "form-action 'self'; " +
           "base-uri 'self'"
}

五、常见威胁防护 #

5.1 XSS 防护 #

typescript
// 输入验证
function sanitizeInput(input: string): string {
    return input
        .replace(/&/g, '&')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#x27;');
}

// 使用 DOM API 而非 innerHTML
element.textContent = userInput;  // ✅ 安全
element.innerHTML = userInput;    // ❌ 危险

5.2 命令注入防护 #

rust
// ❌ 危险:直接拼接用户输入
fn dangerous_command(user_input: &str) {
    let output = Command::new("sh")
        .arg("-c")
        .arg(format!("echo {}", user_input))
        .output();
}

// ✅ 安全:使用参数数组
fn safe_command(user_input: &str) {
    let output = Command::new("echo")
        .arg(user_input)
        .output();
}

5.3 路径遍历防护 #

rust
use std::path::{Path, PathBuf};

fn safe_path(base: &Path, user_path: &str) -> Result<PathBuf, String> {
    let full_path = base.join(user_path);
    
    // 规范化路径
    let canonical = full_path.canonicalize()
        .map_err(|e| e.to_string())?;
    
    // 检查是否在基础目录内
    let base_canonical = base.canonicalize()
        .map_err(|e| e.to_string())?;
    
    if !canonical.starts_with(&base_canonical) {
        return Err("Path traversal detected".to_string());
    }
    
    Ok(canonical)
}

5.4 敏感数据保护 #

rust
// 不记录敏感数据
#[tauri::command]
fn login(username: String, password: String) -> Result<User, String> {
    // ❌ 不要记录密码
    // println!("Login attempt: {} - {}", username, password);
    
    // ✅ 只记录必要信息
    println!("Login attempt for user: {}", username);
    
    // 验证后立即清除
    let result = verify_credentials(&username, &password);
    
    Ok(result)
}

六、安全配置 #

6.1 禁用开发工具 #

json
// tauri.conf.json
{
    "app": {
        "security": {
            "devtools": false
        }
    }
}

6.2 禁用远程内容 #

json
{
    "security": {
        "csp": "default-src 'self'",
        "dangerousRemoteDomainIpcAccess": []
    }
}

6.3 安全窗口配置 #

json
{
    "windows": [{
        "webPreferences": {
            "nodeIntegration": false,
            "contextIsolation": true,
            "sandbox": true
        }
    }]
}

七、安全审计 #

7.1 依赖审计 #

bash
# Rust 依赖审计
cargo audit

# 前端依赖审计
npm audit
pnpm audit

7.2 代码审查清单 #

text
□ 所有用户输入都经过验证和清理
□ 没有硬编码的敏感信息
□ 使用参数化查询防止 SQL 注入
□ 文件路径经过验证
□ 权限配置遵循最小权限原则
□ CSP 配置严格
□ 没有禁用安全特性

八、最佳实践 #

8.1 安全开发流程 #

text
1. 设计阶段:识别安全需求
2. 开发阶段:遵循安全编码规范
3. 测试阶段:安全测试
4. 发布阶段:安全审计
5. 运维阶段:监控和更新

8.2 安全检查清单 #

markdown
## 输入验证
- [ ] 验证所有用户输入
- [ ] 使用白名单验证
- [ ] 限制输入长度

## 输出编码
- [ ] HTML 实体编码
- [ ] URL 编码
- [ ] JavaScript 编码

## 认证授权
- [ ] 强密码策略
- [ ] 会话管理
- [ ] 权限检查

## 数据保护
- [ ] 敏感数据加密
- [ ] 安全存储
- [ ] 传输加密

九、总结 #

9.1 核心要点 #

要点 说明
进程隔离 前后端隔离运行
权限控制 细粒度权限管理
CSP 内容安全策略
输入验证 防止注入攻击
数据保护 敏感数据加密

9.2 下一步 #

现在你已经了解了安全架构,接下来让我们学习 权限控制,深入了解 Tauri 的权限系统!

最后更新:2026-03-28