Tauri 在安全设计上有一条贯穿始终的原则:默认拒绝一切,按需显式授权。这在内容安全策略(Content Security Policy,简称 CSP)上体现得尤为明显。
默认策略:不信任任何内联代码与外部资源
当你用 Tauri 创建一个新项目时,它会自动为你生成一段极为严格的 CSP,通常看起来是这样:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
逐条拆解,它实际在做这几件事:
default-src 'self'——所有资源(图片、字体、XHR 请求等)默认只能从当前应用自身加载,禁止加载任何外部 CDN 或第三方域名资源。script-src 'self'——只允许执行同源的 JavaScript 文件,禁止内联脚本(<script>标签直接写的代码、onclick等事件属性)以及eval()、setTimeout字符串参数等动态代码执行方式。style-src 'self' 'unsafe-inline'——样式表允许从同源加载,同时也允许内联样式(这是为了保留前端开发的基本便利性)。
> 注意:许多项目会完全去掉 'unsafe-inline',改用动态样式注入或 CSS 模块来保持安全,但在默认模板中,Tauri 对内联样式做了一定的妥协。
为什么默认就这么严格?
在一个桌面应用中,WebView 是被当作 UI 层来用的,但它依然有执行 JavaScript 的能力。如果不在应用层面加一层强约束:
- 一旦前端出现 XSS 漏洞,攻击者注入的恶意脚本可以随意加载外部支付页面、窃取本地存储的 token、发起钓鱼窗口。
eval()可以让攻击者动态执行任意字符串,追溯困难。- 加载外部资源可能造成数据外泄(例如请求一个带敏感信息的图片地址)。
Tauri 的默认 CSP 直接把浏览器沙箱的那套“同源限制 + 禁止内联脚本”的强隔离搬到了桌面应用中,让 WebView 内的 JS 环境即使被成功注入恶意代码,也无法突破同源加载外部资源或执行复杂攻击逻辑。
开发者需要知道的:如何根据需求调整 CSP
实际开发中,你可能需要调用外部 API、加载外部字体或图片、使用 WebAssembly 等,这时就需要调整 CSP。Tauri 让你在 tauri.conf.json 中轻松修改,例如:
"security": {
"csp": "default-src 'self'; script-src 'self'; connect-src 'self' https://api.example.com; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'"
}
几点实用建议:
- 保留
script-src 'self',尽量不要加'unsafe-eval'或'unsafe-inline',除非你真的有特殊库依赖它们(例如某些老旧的模板引擎)。绕过内联脚本限制的最好办法是将逻辑全部放到.js文件中。 - 如果你的应用需要加载外部图片(例如从网络相册),添加
img-src https:允许所有 HTTPS 图片,或指定具体域名。 - 调用外部 API 时,在
connect-src中添加对应的域名;使用 WebSocket 同理。 - 如果引入了 WebAssembly,请添加
script-src 'self' 'wasm-unsafe-eval'(注意这是专门的指令,不是通用的unsafe-eval)。
真实场景:如何验证你的 CSP 有没有生效?
可以在开发者工具的控制台中直接看到被 CSP 阻止的请求,例如:
Refused to load the image ‘https://evil.com/steal.png’ because it violates the following Content Security Policy directive: “img-src ‘self’ data:”.
这就是你的 CSP 起作用了。利用这个反馈,你能快速调试出哪些资源需要被加白,同时确保白名单是最小化的。
简而言之,Tauri 那行默认的 CSP 就是你应用的第一道“防火墙”,它直观、暴力,没有运行时开销,但能有效阻断一大类前端攻击向量。保持它严格,只对真正必需的资源开绿灯,是构建可信桌面应用的基本动作。