在 Laravel 8 中使用多个中间件组合路由

发布于 2025-01-09 15:10:19 字数 4058 浏览 1 评论 0原文

我将在我的应用程序中将所有路由分配给管理员角色,一些路由分配给操作角色,一些路由分配给其他角色。我尝试在 Laravel 8 中使用组中间件。

仅管理角色的代码就可以正常工作。但是,当我将中间件添加到路由组中的其他角色时,它并没有按照我的预期运行。

我的代码:

Web.php:

    Route::middleware(['role:Admin'])->group(function () {
        Route::get('/', function () {
            return redirect('/home');
        });
     
        Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
        
        Route::get('/employee_register', [App\Http\Controllers\EmployeeRegisterController::class, 'index'])->name('employee_register');
        
        Route::post('/employee_register', [App\Http\Controllers\EmployeeRegisterController::class, 'save'])->name('employee_save');
        
        Route::post('/DoAsync', [App\Http\Controllers\AjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
        Route::get('/job_booking', [App\Http\Controllers\JobBookingController::class, 'index'])->name('job_booking');
        
        Route::post('/DoAsync_jb', [App\Http\Controllers\JobBookingAjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
        Route::post('/DoAsync_ai', [App\Http\Controllers\AssignInchargeAjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
    });

    
Route::middleware(['role:operation'])->group(function () {
        
        Route::get('/', function () {
        
            return redirect('/job_booking');
        
        });
     
        
        Route::get('/home', function(){
        
            return redirect('/job_booking');
    
        })->name('home');
        
        
        Route::get('/job_booking', [App\Http\Controllers\JobBookingController::class, 'index'])->name('job_booking');
        
        Route::post('/DoAsync_jb', [App\Http\Controllers\JobBookingAjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
        Route::post('/DoAsync_ai', [App\Http\Controllers\AssignInchargeAjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
    });

中间件 (EnsureUserHasRole):

class EnsureUserHasRole
    {
        
        public function handle(Request $request, Closure $next, string $role)
        {
            
            //I received Call to a member function roles() on null error when accessing login and logout. 
            // So, I used this to avoid role check on login & logout routes.
            
            if ( $request->route()->named('login') || $request->route()->named('logout') ) {
                
                return $next($request);
    
            }
            
             
            elseif ($request->user()->roles()->where('role', '=', $role)->exists()) {
    
                return $next($request);
    
            }
                    
            abort(403);
    
        }
    
    }

模型:

用户:

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    
    protected $fillable = [
        'employee_id',
        'name',
        'email',
        'password',
    ];

    
    protected $hidden = [
        'password',
        'remember_token',
    ];

    
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];


    public function roles()
    {
        return $this->belongsToMany(Role::class, 'role_user');
    }
    
}

角色:

class Role extends Model
{
    use HasFactory;

    public function users()
    {
        return $this->belongsToMany(User::class, 'role_user');
    }
    
}

没有第二个中间件 (middleware(['role:operation'])< /code>),所有路由都将被访问。但是,添加它后,EnsureUserHasRole 中间件中的 if 条件会执行 abort(403)

我应该使用任何 if > 在 web.php 的中间件中?

注意:middleware('only.ajax') 用于确保仅在 Ajax 调用时访问控制器

I'm going to assign all routes to Admin role, a few routes to operation role and a few routes to other roles in my App. I've tried to use group middleware in Laravel 8.

The code for Admin Role alone works fine. But, when I add middleware to other roles in the route group, it's not functioned how I expected.

My code:

Web.php:

    Route::middleware(['role:Admin'])->group(function () {
        Route::get('/', function () {
            return redirect('/home');
        });
     
        Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
        
        Route::get('/employee_register', [App\Http\Controllers\EmployeeRegisterController::class, 'index'])->name('employee_register');
        
        Route::post('/employee_register', [App\Http\Controllers\EmployeeRegisterController::class, 'save'])->name('employee_save');
        
        Route::post('/DoAsync', [App\Http\Controllers\AjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
        Route::get('/job_booking', [App\Http\Controllers\JobBookingController::class, 'index'])->name('job_booking');
        
        Route::post('/DoAsync_jb', [App\Http\Controllers\JobBookingAjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
        Route::post('/DoAsync_ai', [App\Http\Controllers\AssignInchargeAjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
    });

    
Route::middleware(['role:operation'])->group(function () {
        
        Route::get('/', function () {
        
            return redirect('/job_booking');
        
        });
     
        
        Route::get('/home', function(){
        
            return redirect('/job_booking');
    
        })->name('home');
        
        
        Route::get('/job_booking', [App\Http\Controllers\JobBookingController::class, 'index'])->name('job_booking');
        
        Route::post('/DoAsync_jb', [App\Http\Controllers\JobBookingAjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
        Route::post('/DoAsync_ai', [App\Http\Controllers\AssignInchargeAjaxController::class,'ajaxTask'])->middleware('only.ajax');
        
    });

The Middleware
(EnsureUserHasRole):

class EnsureUserHasRole
    {
        
        public function handle(Request $request, Closure $next, string $role)
        {
            
            //I received Call to a member function roles() on null error when accessing login and logout. 
            // So, I used this to avoid role check on login & logout routes.
            
            if ( $request->route()->named('login') || $request->route()->named('logout') ) {
                
                return $next($request);
    
            }
            
             
            elseif ($request->user()->roles()->where('role', '=', $role)->exists()) {
    
                return $next($request);
    
            }
                    
            abort(403);
    
        }
    
    }

Models:

User:

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    
    protected $fillable = [
        'employee_id',
        'name',
        'email',
        'password',
    ];

    
    protected $hidden = [
        'password',
        'remember_token',
    ];

    
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];


    public function roles()
    {
        return $this->belongsToMany(Role::class, 'role_user');
    }
    
}

Role:

class Role extends Model
{
    use HasFactory;

    public function users()
    {
        return $this->belongsToMany(User::class, 'role_user');
    }
    
}

Without the second Middleware (middleware(['role:operation'])), all routes would be accessed. But, then adding it, the if condition in EnsureUserHasRole middleware executes the abort(403)

Should I use any if in the middleware in web.php?

Note: middleware('only.ajax') has been used to ensure the controller is accessed only on Ajax call

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最舍不得你 2025-01-16 15:10:19

您正在复制路线。如果你运行 php artisan route:list ,你会发现一半的路由丢失了。

让我们以路由 '/' 为例,您所做的与此类似:

Route::get('/', function () {
    return redirect('/home');
})->middleware(['role:Admin']);

Route::get('/', function () {
    return redirect('/job_booking');
})->middleware(['role:operation']);

如您所见,路由重复。

为了避免这种情况,您需要在路线中添加前缀,例如:

Route::get('/admin', function () {
    return redirect('/home');
})->middleware(['role:Admin']);

Route::get('/operation', function () {
    return redirect('/job_booking');
})->middleware(['role:operation']);

查看 Laravel路由了解更多信息。

You are duplicating the routes. If you run php artisan route:list you will notice that half of your routes are missing.

Lets take an example route '/', what you did is similar to this:

Route::get('/', function () {
    return redirect('/home');
})->middleware(['role:Admin']);

Route::get('/', function () {
    return redirect('/job_booking');
})->middleware(['role:operation']);

As you can see routes duplicates.

To avoid this you need to add prefix to your routes like:

Route::get('/admin', function () {
    return redirect('/home');
})->middleware(['role:Admin']);

Route::get('/operation', function () {
    return redirect('/job_booking');
})->middleware(['role:operation']);

Check out Laravel Routing for more information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文