Auth::check()返回false主因是中间件顺序错误,StartSession必须在Authenticate之前;API应使用auth:api并返回JSON响应,Web路由才重定向;多守卫为“或”关系,需确认guard配置正确且缓存已清。

中间件里 Auth::check() 返回 false 怎么办
不是 Auth 没登录,而是中间件执行时 session 还没加载或被重置。Laravel 的中间件顺序很关键:StartSession 必须在认证中间件之前运行,否则 Auth::check() 永远是 false。
- 检查
app/Http/Kernel.php中$middlewareGroups['web']顺序,确保\Illuminate\Session\Middleware\StartSession::class在\App\Http\Middleware\Authenticate::class之前 - 别在
$middleware(全局中间件)里放认证逻辑——它不走 session,只适用于无状态场景 - 如果用了自定义认证中间件,别手动调
Auth::guard()->user()前忘了Auth::guard()->check(),guard 实例可能未初始化
401 Unauthorized 被转成 302 重定向到登录页
这是 Laravel 默认行为,但 API 请求不该跳转。问题不在认证失败本身,而在你用的中间件类型不对。
- Web 路由默认用
\App\Http\Middleware\Authenticate::class,它遇到未登录就重定向 - API 路由必须显式指定守卫并返回 JSON:在路由定义里加
middleware('auth:api'),且确保config/auth.php中apiguard 的 driver 是token或sanctum - 如果用了 Sanctum,确认请求带了有效的
Authorization: Bearer xxx,且 token 没过期、没被 revoke
自定义中间件中 abort(401) 不生效或报错
常见原因是 abort 被 try/catch 吞了,或者响应已被发送。更稳妥的做法是直接返回响应对象。
- 别在中间件里写
if (!Auth::check()) { abort(401); }——abort()抛异常,在某些上下文(如队列、测试)里会崩 - 改用
return response()->json(['message' => 'Unauthenticated.'], 401);(API 场景)或return redirect()->guest('login');(Web 场景) - 如果中间件里调了其他服务(比如 Redis 或 DB),注意它们可能抛出异常,掩盖了认证失败的真实原因;先做
Auth::check()判断,再执行后续逻辑
多守卫(auth:admin,api)下认证总失败
逗号分隔多个守卫 ≠ 同时满足,而是“任一通过即放行”。但很多人误以为要全部通过,结果配置了不存在的守卫名,导致全挂。
- 检查
config/auth.php里的guards键,确认每个守卫名都正确定义,比如'admin' => ['driver' => 'session', 'provider' => 'admins'] - provider 对应的 model 必须实现
Illuminate\Contracts\Auth\Authenticatable,且$fillable包含password(否则Auth::attempt()写入 session 失败) - 调试时临时加一行
Log::info('Guard used: ' . Auth::getDefaultDriver());,看实际走的是哪个守卫——别信 middleware 字符串,它可能被覆盖
最常被忽略的一点:缓存的 session 或 token 没清理,导致你以为改了代码,其实还在用旧凭证。开发时顺手跑一遍 php artisan config:clear && php artisan cache:clear && php artisan view:clear,再试。










