You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 18:42:34