中间件拦截主因是执行链路中断而非逻辑错误,需重点排查认证注入、权限校验、响应返回三环节:确认认证中间件前置并显式绑定user属性,权限中间件通过$request->getattribute('user')取值且路由命名有效,所有分支必须显式return,cors中间件须置顶并跳过options请求。

中间件验证一直拦截,通常不是逻辑写错了,而是执行链路卡在某个环节——比如用户没注入、路由没匹配上、返回值漏写,或者跨域预检被误杀。重点查三块:认证是否真成功、权限是否真放行、响应是否被提前中断。
确认认证中间件已正确注入用户
权限中间件依赖前置认证中间件提供的用户对象,如果没注入,后续所有校验都会失败拦截。
- 检查
app/middleware.php中认证类(如CheckAuth)是否排在权限类(如CheckPermission)之前 - 认证中间件的
handle()方法里,必须用$request->withAttribute('user', $user)显式绑定,不能只调Auth::user()却不传出去 - 权限中间件中统一用
$request->getAttribute('user')取用户,别直接调Auth::user()—— 后者可能因执行时机问题返回空 - 加一行日志或 trace,比如
trace('user attr: ' . var_export($request->getAttribute('user'), true));,确认用户对象是否真实存在
检查权限校验是否匹配到有效路由名
权限中间件靠路由名($request->rule()->getName())查白名单或节点规则,若取不到或为空,常直接拦截。
- 确保目标路由显式命名,例如
Route::get('api/user', 'Api/UserController@index')->name('api.user.index'); - 在权限中间件中先判空:
$rule = $request->rule(); $routeName = $rule ? $rule->getName() : null;,避免Call to a member function getName() on null - 免登录路径(如
/api/login、/captcha)要写进白名单配置,并用str_starts_with($path, '/api/login')或正则快速放行 - 调试时临时加
trace('route name: ' . $routeName);,看实际匹配的是什么
确保中间件每个分支都显式 return
ThinkPHP 中间件函数末尾隐式返回 null 会被框架视为“中断请求”,导致 401/403 拦截,即使逻辑本身没报错。
- 校验通过时必须写
return $next($request); - 拦截时用
return abort(403);或return redirect('/login');,不能只写abort(403)就结束 - 尤其注意
if-else分支是否全覆盖,比如忘记写else分支里的return $next(...) - 可在中间件开头加
trace('middleware start');,结尾加trace('middleware end');,确认是否执行到末尾
排查跨域预检干扰权限流程
带自定义 Header 或非简单方法(如 POST+JSON)的请求,浏览器会先发 OPTIONS 预检。如果中间件没处理它,就可能被权限或签名中间件误拦。
- CORS 中间件必须注册在
app/middleware.php数组最前面,确保它最先响应 OPTIONS 请求 - 权限/签名中间件里要主动跳过 OPTIONS:
if ($request->isOptions()) { return response('', 204); } - 不要让签名中间件去验 OPTIONS 请求的
sign—— 它本来就没有业务参数,验签必然失败 - 前端 fetch 调用记得加
{ credentials: 'include' },后端响应头中Access-Control-Allow-Origin必须是具体域名,不能是*
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











