主题
CSP(内容安全策略)构建
Livewire 提供了一个 CSP 安全构建,允许您在禁止 'unsafe-eval' 的严格内容安全策略(CSP)标头环境中使用 Livewire 应用程序。
什么是内容安全策略(CSP)?
内容安全策略(CSP)是一种安全标准,有助于防止各种类型的攻击,包括跨站脚本(XSS)和代码注入攻击。CSP 通过允许 Web 开发人员控制浏览器允许加载和执行哪些资源来工作。
为什么 CSP 影响 Livewire
Livewire(及其底层的 Alpine.js 框架)默认使用 new Function() 声明来编译和执行 HTML 属性中的 JavaScript 表达式,例如:
html
<button wire:click="$set('count', count + 1)">Increment</button>
<div wire:show="user.role === 'admin'">Admin panel</div>虽然这种方法比直接使用 eval() 更快更安全,但它仍然违反了许多注重安全的应用程序强制执行的 'unsafe-eval' CSP 指令。
启用 CSP 安全模式
要启用 Livewire 的 CSP 安全模式,您需要修改应用程序的配置:
配置
在您的 config/livewire.php 文件中,将 csp_safe 选项设置为 true:
php
'csp_safe' => true,对 Alpine.js 的影响
重要提示:当您在 Livewire 中启用 CSP 安全模式时,它还会影响应用程序中的所有 Alpine.js 功能。Alpine 将自动使用其 CSP 安全评估器,这意味着应用程序中的所有 Alpine 表达式都将受到相同的解析限制。
这就是大多数开发人员会注意到约束的地方,因为 Alpine 表达式往往比典型的 Livewire 表达式更复杂。
支持的功能
CSP 构建支持 Livewire 中使用的大多数常见 JavaScript 表达式:
基本 Livewire 表达式
html
<!-- 以下示例有效 -->
<button wire:click="increment">+</button>
<button wire:click="decrement">-</button>
<button wire:click="reset">Reset</button>
<button wire:click="save">Save</button>
<input wire:model="name">
<input wire:model.live="search">带参数的方法调用
html
<!-- 以下示例有效 -->
<button wire:click="updateUser('John', 25)">Update User</button>
<button wire:click="setCount(42)">Set Count</button>
<button wire:click="saveData({ name: 'John', age: 30 })">Save Object</button>属性访问和更新
html
<!-- 以下示例有效 -->
<input wire:model="user.name">
<input wire:model="settings.theme">
<button wire:click="$set('user.active', true)">Activate</button>
<div wire:show="user.role === 'admin'">Admin Panel</div>Alpine 中的基本表达式
html
<!-- 以下示例有效 -->
<div x-data="{ count: 0, name: 'Livewire' }" wire:ignore>
<button x-on:click="count++">Increment</button>
<span x-text="count"></span>
<span x-text="'Hello ' + name"></span>
<div x-show="count > 5">Count is high!</div>
</div>不支持的功能
某些高级 JavaScript 功能在 CSP 安全模式下无法使用:
复杂的 JavaScript 表达式
html
<!-- ❌ 以下示例无效 -->
<button wire:click="items.filter(i => i.active).length">Count Active</button>
<div wire:show="users.some(u => u.role === 'admin')">Has Admin</div>
<button wire:click="(() => console.log('Hi'))()">Complex Function</button>模板字面量和高级语法
html
<!-- ❌ 以下示例无效 -->
<div x-text="`Hello ${name}`">Bad</div>
<div x-data="{ ...defaults }">Bad</div>
<button x-on:click="() => doSomething()">Bad</button>动态属性访问
html
<!-- ❌ 以下示例无效 -->
<div wire:show="user[dynamicProperty]">Bad</div>
<button wire:click="this[methodName]()">Bad</button>解决限制的方法
对于复杂的 Alpine 表达式,使用 Alpine.data() 或将逻辑移至方法中:
html
<!-- 使用复杂内联表达式的替代方案 -->
<div x-data="users">
<div x-show="hasActiveAdmins">Admin panel available</div>
<span x-text="activeUserCount">0</span>
</div>
<script nonce="[nonce]">
Alpine.data('users', () => ({
users: ...,
get hasActiveAdmins() {
return this.users.filter(u => u.active && u.role === 'admin').length > 0;
},
get activeUserCount() {
return this.users.filter(u => u.active).length;
}
}));
</script>CSP 标头示例
以下是与 Livewire 的 CSP 安全构建兼容的 CSP 标头示例:
Content-Security-Policy: default-src 'self';
script-src 'nonce-[random]' 'strict-dynamic';
style-src 'self' 'unsafe-inline';关键点:
- 从您的
script-src指令中删除'unsafe-eval' - 使用基于 nonce 的脚本加载,带有
'nonce-[random]' - 考虑添加
'strict-dynamic'以更好地兼容动态加载的脚本
性能考虑
CSP 安全构建使用不同的表达式评估器:
- 解析:表达式的初始解析稍慢(通常可以忽略不计)
- 运行时:对于简单表达式,运行时性能相似
- 包大小:由于自定义解析器,JavaScript 包略大
对于大多数应用程序来说,这些差异几乎无法察觉,但值得使用您的特定用例进行测试。
测试您的 CSP 实现
要验证您的 CSP 设置是否正常工作:
- 在 Web 服务器或应用程序中启用 CSP 标头
- 在浏览器开发工具中测试 - CSP 违规将出现在控制台中
- 验证表达式工作 - 所有 Livewire 和 Alpine 表达式应正常运行
- 检查控制台错误 - 不应出现
unsafe-eval违规
何时使用 CSP 安全模式
在以下情况下考虑使用 CSP 安全模式:
- 您的应用程序需要严格的 CSP 合规性
- 您正在为安全敏感环境构建应用程序
- 您组织的安全策略禁止
'unsafe-eval' - 您正在部署到具有强制 CSP 限制的平台