在 Laravel 8 中使用多个中间件组合路由
我将在我的应用程序中将所有路由分配给管理员角色,一些路由分配给操作角色,一些路由分配给其他角色。我尝试在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您正在复制路线。如果你运行 php artisan route:list ,你会发现一半的路由丢失了。
让我们以路由
'/'
为例,您所做的与此类似:如您所见,路由重复。
为了避免这种情况,您需要在路线中添加前缀,例如:
查看 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:As you can see routes duplicates.
To avoid this you need to add prefix to your routes like:
Check out Laravel Routing for more information.