Locked
#[Locked] 属性阻止属性在客户端被修改,保护模型 ID 等敏感数据不被用户篡改。
基本用法
将 #[Locked] 属性应用到任何不应从前端更改的公共属性上:
php
<?php // resources/views/components/post/⚡show.blade.php
use Livewire\Attributes\Locked;
use Livewire\Component;
use App\Models\Post;
new class extends Component {
#[Locked] // [tl! highlight]
public $postId;
public function mount($id)
{
$this->postId = $id;
}
public function delete()
{
Post::find($this->postId)->delete();
return redirect('/posts');
}
};若用户试图通过浏览器开发者工具或篡改请求来修改被锁定的属性,Livewire 将抛出异常并阻止操作执行。
WARNING
后端修改仍然允许
带有 #[Locked] 属性的属性仍可在组件的 PHP 代码中修改。锁定仅防止客户端篡改。请注意不要在自己的方法中将不可信的用户输入传给被锁定的属性。
何时使用
在以下情况使用 #[Locked]:
- 存储绝不应被用户更改的模型 ID
- 在整个组件生命周期中保留与授权相关的敏感数据
- 保护任何充当安全边界的公共属性
TIP
模型属性默认是安全的
若将 Eloquent 模型存储在公共属性中,Livewire 会自动确保 ID 不被篡改——无需 #[Locked] 属性:
php
<?php // resources/views/components/post/⚡show.blade.php
use Livewire\Component;
use App\Models\Post;
new class extends Component {
public Post $post; // Already protected [tl! highlight]
public function mount($id)
{
$this->post = Post::find($id);
}
};为什么不用 protected 属性?
你可能会疑惑:为什么不能直接用 protected 属性存放敏感数据。
请记住,Livewire 仅在请求之间持久化公共属性。protected 属性适用于静态、硬编码的值,但任何需要在运行时保存的数据都必须使用公共属性,才能在请求之间正确持久化。
这正是 #[Locked] 的关键所在:它既提供公共属性的持久化能力,又防止客户端篡改。
Livewire 不能自动做到吗?
在理想情况下,Livewire 会默认锁定属性,仅在该属性使用了 wire:model 时才允许修改。
遗憾的是,这需要 Livewire 解析你所有的 Blade 模板,以判断属性是否被 wire:model 或类似 API 修改。
这不仅会增加技术与性能开销,而且若属性被 Alpine 或其他自定义 JavaScript 修改,也无法检测。
因此,Livewire 将继续默认让公共属性可自由修改,并提供工具让开发者按需锁定它们。