Laravel中间件中Auth::id()返回NULL的认证问题求助
解决Laravel中间件中Auth::id()返回NULL的问题
嘿,我来帮你搞定这个问题!你遇到的核心问题是中间件执行顺序不对——你的日志中间件被放在了全局$middleware数组里,而Laravel的认证流程(包括Passport的Token验证)是在路由中间件组里执行的,全局中间件会先于路由中间件运行,这时候用户还没完成认证,所以Auth::id()自然返回NULL。
下面是两种可行的解决方案,优先推荐第一种:
方案1:将日志中间件移到路由中间件组(推荐)
这种方法最贴合Laravel的中间件设计逻辑,能确保只有经过认证的请求才会触发日志记录:
先在
app/Http/Kernel.php的$routeMiddleware数组中注册你的中间件:protected $routeMiddleware = [ // 其他已有的中间件... 'log.activity' => \App\Http\Middleware\YourLogMiddleware::class, // 替换成你的中间件类名 ];把它加到对应的路由中间件组里(如果是API路由就加
api组,web路由就加web组),必须放在认证中间件之后:protected $middlewareGroups = [ 'api' => [ 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, 'auth:api', // Passport的认证中间件,先执行它完成用户认证 'log.activity', // 放在认证中间件之后,此时用户已被识别 ], // web组同理,将日志中间件放到`auth`中间件之后 ];
调整后,中间件会在Passport完成用户认证后执行,Auth::id()就能正常获取当前登录用户的ID了。
方案2:全局中间件中手动认证用户(仅当必须用全局中间件时使用)
如果因为特殊需求必须把中间件留在全局数组里,可以手动通过请求中的Bearer Token来认证用户:
public function handle(Request $request, Closure $next) { // 尝试通过Bearer Token获取并认证用户 if ($token = $request->bearerToken()) { $passportToken = \Laravel\Passport\Token::findToken($token); if ($passportToken && !$passportToken->revoked) { Auth::setUser($passportToken->user); } } // 仅当用户认证成功时记录活动 if (Auth::check()) { Activity::create([ 'user_id' => Auth::id(), 'ip_id' => SecureAgent::getIP(), 'action' => $request->method(), 'page' => $request->path() ]); } return $next($request); }
不过这种方法会增加全局中间件的开销,还需要自己处理Token过期、吊销等边缘情况,不如方案1优雅。
额外补充:全局中间件会作用于所有请求(包括未认证的请求),移到路由组后还能避免对未认证请求执行无用的日志逻辑,效率更高。
内容的提问来源于stack exchange,提问作者Rade Ilijev
相关产品推荐
相关产品推荐

