必须在policy或中间件中显式拦截非授权用户的restore请求,因laravel软删除默认无访问控制,restore()方法对所有有写权限用户开放,需手动定义userpolicy::restore()并用$this->authorize('restore', $user)校验。

软删除记录被普通用户恢复了怎么办
默认 restore() 方法对所有有模型写权限的用户开放,没做任何角色校验。Laravel 的软删除本身不带访问控制,restore() 和 forceDelete() 一样只是 Eloquent 方法,调用即执行。
常见错误现象:前端按钮没隐藏、API 接口没拦截、策略里漏写了 restore 能力判断,结果普通用户发个 PATCH /users/123/restore 就把删掉的敏感数据拉回来了。
- 必须在 Policy 或中间件中显式拦截非授权用户的
restore请求 - 不要依赖「用户看不到按钮」来保证安全——接口层必须校验
-
restore()不触发updating或updated事件,但会触发restoring和restored,可在这里加二次校验(但别只靠这个)
Laravel Policy 中怎么限制 restore 权限
Policy 是最自然的落点,但很多人只写了 view、update、delete,忘了 restore 是独立方法,需要手动定义。
使用场景:你已用 php artisan make:policy UserPolicy --model=User 生成策略,现在要补上分级逻辑。
PHP中文网提供Laravel 13.2.0版本下载,Laravel框架 是基于 PHP 8.3+ 的高性能框架,官方推荐通过 Composer 安装。它内置 AI SDK、JSON:API Resources 及原生向量搜索,支持属性驱动开发与队列路由,大幅提升开发效率。相比旧版,13.2.0 优化了缓存 TTL 管理与实时通信,无需 Redis 即可横向扩展。作为现代 Web 开发首选,它兼顾安全与极速体验,助您快速构建企业级应用。
- 在
UserPolicy中添加 public functionrestore($user, $userModel) { … } - 检查角色时别只看
$user->is_admin—— 更可靠的是$user->hasRole('super-admin')(如果你用 spatie/laravel-permission) - 返回
false时,Gate::authorize('restore', $userModel)会抛出Illuminate\Auth\Access\AuthorizationException - 控制器里必须调用
$this->authorize('restore', $user),否则 Policy 不生效
restore() 调用前没查权限导致 500 错误
直接调用 $model->restore() 而不走 Gate 校验,等于绕过所有权限逻辑。更危险的是,如果模型已被硬删除(forceDelete),再调 restore() 会报错 Call to a member function restore() on null。
性能影响:restore() 本身是单条 UPDATE,但若你在 Policy 的 restore 方法里做了 N+1 查询(比如反复查角色权限表),就会拖慢整个恢复流程。
- 永远用
$model->withTrashed()->find($id)先取模型,确保它存在且是软删除状态 - Policy 中避免在
restore方法里调用$user->roles()等关系查询;提前把权限标识缓存到用户实例上(如$user->is_super_admin) - 控制器里别写
if ($user->can('restore', $model)) { $model->restore(); }—— 这种写法跳过了 Gate 的异常处理机制,应该统一用$this->authorize()
API 接口恢复软删除资源时 403 却没提示原因
前端点了恢复按钮,接口返回 403,但响应体空或只有 {"message": "This action is unauthorized."},用户不知道是权限不够还是别的问题。
兼容性注意:Laravel 9+ 默认的 HandleExceptions 对 AuthorizationException 返回 403,但不会附带具体拒绝理由,这对调试和前端友好度都不够。
- 在
app/Exceptions/Handler.php的render方法中单独捕获AuthorizationException - 返回 JSON 时加字段,例如
['error' => 'insufficient_permissions', 'action' => 'restore'] - 别在 Policy 的
restore方法里 throw 新异常——会覆盖原有上下文,让日志难追踪










