Laravel自定义包中调用中间件并实现鉴权的问题
解决Laravel自定义包中中间件调用无效及Auth::user()返回null的问题
我之前也碰到过类似的场景,咱们一步步拆解问题、解决问题:
首先你遇到的两个核心问题是关联的:中间件调用无效,以及Auth::user()始终返回null,本质是中间件的注册和执行顺序出了问题。
1. 先给自定义中间件注册别名
你创建的RoleMiddleware虽然放在了默认中间件目录,但Laravel不会自动识别'role'这个别名,必须手动注册到路由中间件列表:
打开app/Http/Kernel.php,找到$routeMiddleware数组,添加一行:
protected $routeMiddleware = [ // 保留其他已有的中间项 'role' => \App\Http\Middleware\RoleMiddleware::class, ];
这样Laravel才能把你在控制器里写的'role'和对应的中间件类关联起来。
2. 调整中间件执行顺序,让Auth相关逻辑先跑
Auth::user()返回null的核心原因是:你的RoleMiddleware在认证中间件之前执行了,此时用户会话还没初始化,自然拿不到用户实例。
Laravel的web中间件组包含了StartSession、AuthenticateSession等和会话、认证相关的关键中间件,必须让它们先于RoleMiddleware执行:
方案一:在控制器构造函数中指定执行顺序
修改包内CaseController的构造函数:
public function __construct() { // 先执行web中间件组,再执行role中间件 $this->middleware(['web', 'role'], ['except' => 'caseUrlView']); }
方案二:确保路由包裹在web中间件组内
如果是在项目默认的web.php里定义包的路由,要把路由放到web中间件组里:
Route::middleware('web')->group(function () { // 你的包相关路由 Route::get('/cases', [\App\Package\Cases\src\Http\Controllers\CaseController::class, 'index']); });
如果是包自身的路由文件,注册时也要明确指定web中间件。
3. 优化RoleMiddleware的冗余逻辑
顺便帮你简化下中间件里重复的判断,让逻辑更清晰:
class RoleMiddleware { public function handle($request, Closure $next) { // 未认证直接跳登录页 if (!Auth::check()) { return redirect('login'); } $user = $request->user(); // 用户实例不存在直接404 if (!$user) { abort(404); } $roles = Role::all()->pluck('slug'); // 无对应角色直接404 if (!$user->hasRole($roles)) { abort(404); } return $next($request); } }
最后验证
做完以上步骤后,先清理缓存:
php artisan config:clear php artisan route:clear
然后重新测试:
- 未登录状态访问目标页面,会自动跳转登录页
- 登录成功后,
Auth::user()能正常返回用户实例 - 中间件的角色校验逻辑也会正常生效
内容的提问来源于stack exchange,提问作者fazy
相关产品推荐
相关产品推荐

