auth中间件核心是验证守卫是否认证成功,而非主动获取用户;它调用guard的authenticate()方法,认证通过后auth::user()才返回实例;常见错误是未正确配置guard驱动或请求缺少凭证。

auth中间件怎么拿到已登录用户
关键不是“拿”,而是“守卫是否已认证成功”。auth 中间件本身不主动获取用户,它调用当前 guard(比如 session 或 token)的 authenticate() 方法;只有 guard 内部完成验证后,Auth::user() 才会返回模型实例。
常见错误是:在中间件里写 $request->user() 却得到 null——这说明 guard 还没运行,或者 guard 配置的 driver 不匹配请求场景(例如用 web guard 去验 API 请求头里的 token)。
- Web 路由默认走
webguard,依赖 session + cookie - API 路由需显式指定
auth:api,对应apiguard,驱动必须是token、jwt或sanctum - 检查
config/auth.php里guards.api.driver的值是否和你实际使用的认证方式一致
自定义中间件里如何复用Laravel认证逻辑
别自己查数据库比对 token 或 session ID。直接复用 Laravel 的 guard 接口最安全、最省事。
例如你要写一个只允许管理员访问的中间件,正确做法是:
public function handle($request, Closure $next)
{
if (!Auth::check()) {
return response(['msg' => '未登录'], 401);
}
$user = Auth::user();
if (!$user->is_admin) { // 假设模型有 is_admin 字段
return response(['msg' => '权限不足'], 403);
}
return $next($request);
}
这样既用了 Laravel 的 session 恢复/Token 解析逻辑,又避免重复实现认证流程。
- 不要在中间件里手动调用
DB::table('users')->where(...)查用户——绕过了 guard 的生命周期和事件 - 如果需要额外鉴权(如 appid/appsecret),应该放在 guard 之前(比如加一个前置中间件),而不是替代 guard
-
Auth::guard('api')->user()可以显式指定守卫,适合多 guard 场景
为什么 auth:api 中间件对某些请求无效
最常见原因是请求没带认证凭证,或凭证格式不对。
Laravel 的 token guard 默认从请求头 Authorization: Bearer {token} 读取;sanctum 则优先检查 Authorization 头, fallback 到 cookie;jwt 同样依赖 Bearer 头。
- 前端发请求时漏了
Authorization头,或写成Token xxx(少Bearer) - API 路由注册在
routes/web.php而非routes/api.php,导致没加载apimiddleware group -
config/auth.php中guards.api.provider指向的 model 没实现Authenticatable,或$fillable漏了api_token
调试时可临时在中间件里加 dd($request->header('Authorization'), Auth::guard('api')->check()) 看哪一步断了。
中间件顺序影响认证结果
Kernel.php 里中间件的注册顺序直接影响能否走到 auth。
比如你加了一个日志中间件,但它在 StartSession 之前执行,那 session 就还没启动,auth:web 必然失败;又比如你把 CORS 中间件放在 auth 后面,但预检请求(OPTIONS)被拦在 auth 之前,导致跨域失败。
-
StartSession必须在auth:web之前 -
EncryptCookies和AddQueuedCookiesToResponse要配对,否则 session cookie 解密失败 - 自定义鉴权中间件(如校验 appid)应放在
auth之前,作为第一道过滤
真正容易被忽略的是:auth 中间件本身不处理未登录跳转逻辑——它只抛异常或返回响应,最终重定向行为由 Illuminate\Auth\Middleware\EnsureLogin 或你的异常处理器决定。这点一旦配置错,就会出现“没报错但也不跳转”的静默失败。











