中间件不保护基于角色的路由 [英] Middleware doesn't protect routes based on role
本文介绍了中间件不保护基于角色的路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
Can't protect Routes based on role Laravel 8
我遇到的问题是,我尝试使用中间件仅在某些路由具有各自的角色时才允许它们访问。
我的中间件代码是这样的(即我上一个问题的答案中建议的代码)。
<?php
namespace AppHttpMiddleware;
use Closure;
use IlluminateHttpRequest;
class EnsureUserHasRole
{
/**
* Handle an incoming request.
*
* @param IlluminateHttpRequest $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next, $role)
{
if (! $request->user()->role($role)->get()) {
// Redirect...
return back();
}
return $next($request);
}
}
我的用户模型的代码是
<?php
namespace AppModels;
use IlluminateContractsAuthMustVerifyEmail;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
use IlluminateDatabaseEloquentModel;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'role',
'name',
'email',
'password',
'idPersona',
'estado'
];
public function Persona(){
return $this->belongsTo(Persona::class,'idPersona');
}
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'remember_token'
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function scopeRole($query, $role)
{
return $query->where('role', $role);
}
}
不确定它是否能提供帮助,但我的数据库中的USER表是这样的
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role` varchar(20) DEFAULT NULL,
`name` varchar(100) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`password` varchar(250) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`remember_token` varchar(255) DEFAULT NULL,
`idPersona` int(11) DEFAULT NULL,
`estado` tinyint(1) NOT NULL DEFAULT 31,
`prueba` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `users_FK` (`idPersona`),
CONSTRAINT `users_FK` FOREIGN KEY (`idPersona`) REFERENCES `personas` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=48 DEFAULT CHARSET=utf8mb4
我正在使用此Route测试我的中间件,在本例中,我尝试只允许administrador
访问该路由,如果不允许,则返回。(中间件角色是上面代码中的角色)。
Route::get('/gestionarMedicos', [PersonaController::class,'mostrarMedicos'])->name('personaMostrarMedicos')->middleware('auth','firstLogin','role:administrador');
问题是所有用户都可以访问它。我认为这是一个逻辑问题,因为如果我使用dd()在IF外部显示IF返回的内容,则它会显示false
,即使在administrador
角色中也是如此。
推荐答案
将您的中间件方法更改为:
public function handle(Request $request, Closure $next, $role)
{
// dd($request->user()->role, $role);
// uncomment this for testing purpose if it's not working, both should be equal to "administrator"
if (!$request->user() || $request->user()->role != $role) {
// Redirect...
return back();
}
return $next($request);
}
您以前拥有的$request->user()->role($role)->get()
将返回管理员集合。
这不是你要找的。您只想检查当前用户$request->user()
是否为管理员。
由于用户有role
列,只需检查您提供的$role
是否相同就足够了。
在英文中,IF语句表示";如果没有用户,或者如果用户的列role
的值不等于$role
,则重定向回";。
如果您需要多个角色怎么办?
使用可变函数(https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list)。
添加...
in函数声明(...$roles
):
public function handle(Request $request, Closure $next, ...$roles)
{
//dd($roles);
//is now an array with all the roles you provided to the route.
if (!$request->user() || !in_array($request->user()->role, $roles)) {
// Redirect...
return back();
}
return $next($request);
}
使用可变函数允许您将字符串参数转换为数组。
在您的路线中,您现在可以添加多个角色:
Route::get('/gestionarMedicos', [PersonaController::class,'mostrarMedicos'])->name('personaMostrarMedicos')->middleware('auth','firstLogin','role:administrador,client,somethingelse');
在中间件中,$roles
等于:
['administrador', 'client', 'somethingelse']
这篇关于中间件不保护基于角色的路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文