TP6.1.5中间件需验证是否真正生效:检查app/middleware.php格式、路由/控制器是否显式绑定、用throw测试执行时机;RBAC须校验角色对应权限而非仅角色存在;allowField必须与validate联用防字段绕过;token须绑定用户及资源ID防复用。

中间件是否真正拦截未授权请求
TP6.1.5 的中间件执行链更严格,但注册错误会导致“看似启用、实则跳过”。必须验证它是否在请求生命周期早期就生效,而不是等控制器都跑完了才调用。
常见错误现象:AuthMiddleware 类存在,app/middleware.php 也写了类名,但未登录用户访问 /admin/user/edit 却直接进入控制器、没返回 403 或跳转;或抛出 Call to a member function check() on null——说明中间件里依赖的 $auth 实例根本没注入成功。
- 检查
app/middleware.php是否存在且格式正确:必须是 return 数组,不能是空文件或只写注释 - 确认中间件是否绑定到目标路由:TP6 不再支持全局自动附加,必须显式调用
Route::middleware([AuthMiddleware::class])或在控制器构造函数中写$this->middleware(AuthMiddleware::class) - 在中间件
handle()开头加一行throw new \Exception('auth middleware hit');,然后 curl 测试接口,看是否立刻中断——这是最直接的“是否运行”验证
RBAC 权限校验是否走完三级链路
TP6 下常见误判:中间件里只查了用户有没有角色($user->roles),却没查该角色是否拥有对应权限($role->permissions),导致“有角色=有全部权限”,完全绕过 RBAC 设计本意。
典型漏洞场景:管理员给某用户分配了 editor 角色,但没给这个角色绑定 user.delete 权限;用户仍能成功提交删除请求——因为中间件只做了 $auth->check('user.edit'),而没校验当前请求实际需要的是 user.delete。
- 权限标识必须用
slug字段(如goods.update),不能用 ID 或中文名,否则路由层无法比对 - 校验前先缓存并判空:
$perms = Cache::remember("user:{$uid}:permissions", 3600, fn () => $user->roles()->with('permissions')->select()->pluck('permissions.*.slug')->flatten()->toArray());,再用in_array('user.delete', $perms) - 避免重复查库:Session 中已有
user_id,不要在中间件里再执行User::find($uid),直接从容器或上下文取
表单字段白名单是否生效且不被绕过
TP6.0+ 的 allowField 是防越权修改的核心防线,但极易被忽略或误用。比如控制器里写了 $model->allowField(['title', 'price'])->save($data),但如果 $data 是通过 $this->request->post() 直接接收,且没配合 validate 或过滤,攻击者仍可 POST is_admin=1 并触发数据库写入——因为 allowField 只控制模型层字段映射,不拦截原始输入。
- 必须和
validate联用:$this->validate($data, 'GoodsEdit')中的规则需显式包含in:title,price,status,拒绝非法字段名 -
allowField必须在save()前调用,且不能被条件分支遗漏(如 if/else 分支中只在一个分支写了) - 禁用
create()和裸save($data);所有更新操作强制走allowField+ 显式字段列表
令牌(token)是否与权限上下文强绑定
TP6 默认开启表单令牌,但默认生成方式不带用户身份信息,导致 A 用户生成的 token 可被 B 用户复用,只要 B 知道表单 URL 和字段结构——这在编辑他人数据时就是严重越权。
错误做法:token() 单独调用,或只传一个字符串名;正确做法必须把当前用户 ID、资源 ID 等关键上下文拼进 token 名称中。
- 生成时绑定身份:
token('edit_goods_'.$goodsId.'_'.$userId) - 验证失败必须阻断并记录:
if (!token('edit_goods_'.$goodsId.'_'.$userId)) { Log::error("Token mismatch for user {$userId} on goods {$goodsId}"); throw new ValidateException('非法请求'); } - 绝不能在配置中设
'token_on' => false,也不要在高危接口(如删除、状态变更)中临时关闭
权限中间件最难测的不是“能不能拦”,而是“拦得够不够细”——比如它是否区分了“编辑自己商品”和“编辑他人商品”,是否识别了字段级权限(如只允许改 price 不允许改 status),这些逻辑往往藏在模型事件或钩子里,光看中间件代码根本发现不了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











