针对不同用户角色的基于角色的身份验证
Role based authentication for different roles of user
我正在使用 laravel 5.5 为用户开发 基于角色的身份验证。
系统用户可以有多个角色,这些角色可以访问多个菜单。
我想检查用户的当前角色是否可以访问特定菜单。
以下是我的table结构
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
});
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->longText('description')->nullable();
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
});
Schema::create('role_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('role_id');
$table->integer('is_default')->default(0);
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')->on('roles')
->onDelete('cascade');
});
Schema::create('menus', function (Blueprint $table) {
$table->increments('id');
$table->integer('parent_id');
$table->string('name')->unique();
$table->string('action')->unique();
$table->integer('sequence');
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
});
Schema::create('menu_roles', function (Blueprint $table) {
$table->increments('id');
$table->integer('menu_id');
$table->integer('role_id');
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
$table->foreign('menu_id')
->references('id')->on('menus')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')->on('roles')
->onDelete('cascade');
});
我定义的关系如下:
User.php
public function roles()
{
return $this->belongsToMany(Role::class);
}
Role.php
public function users()
{
return $this->belongsToMany(User::class);
}
public function menus()
{
return $this->belongsToMany(Menu::class);
}
如何检查特定角色是否可以访问特定菜单?
提前致谢
您必须创建另一个枢轴 table,例如
Schema::create('role_menu', function (Blueprint $table) {
$table->increments('id');
$table->integer('menu_id');
$table->integer('role_id');
$table->foreign('menu_id')
->references('id')->on('menus')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')->on('roles')
->onDelete('cascade');
});
显然,必须有一个menus
table。
打开了很多可能性...我认为更好的方法是创建一个可用于特定菜单路由的中间件。
例如:
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Check user roles in order to check if role has access to the menu
foreach($request->user()->roles as $role) {
// This code supposes that your route is something like http://app.tld/menus/{menu_id}
if($role->menus()->find($request->route('menu_id'))) {
return $next($request);
}
}
// Otherwise abort, redirect.. whatever
abort(401);
}
假设您有一个像 $menuId
这样的变量,您可以简单地将 whereHas() 与经过身份验证的用户一起使用并检查关系是否存在:
$canAccess = auth()->user()->whereHas('roles.menus', function ($query) use($menuId) {
$query->where('id', $menuId);
})->exists();
您可以在用户和角色中进行检查...我会在用户模型中进行检查
像这样的东西应该在用户模型中工作...对于角色,只需删除与用户相关的表。
public function checkMenuPermission($key)
{
// YOUR KEY can be name, id, any unique column...
$results = DB::table('users')
->join('role_user', 'users.id', '=', 'role_user.user_id')
->join('menu_roles', 'role_user.role_id', '=', 'menu_roles.role_id')
->join('menus', 'menus.id', '=', 'menu_roles.menu_id')
->select('menus.name')
->where('users.id', $this->id)
->where('menus.name', $key)
->orderBy('menus.name')
->distinct()
->get()->count();
return $results > 0 ? true : false;
}
然后在你的控制器中就可以像 $user->checkMenuPermission('someSome');
那样调用它
编辑
如果你只想用 Eloquent 做,你可以
public function checkMenuPermission($key){
foreach($this->menus as $m){
if($m->name == $key){
return true;
}
}
return false;
}
你知道政策是如何运作的吗?
在这种情况下,它应该对您有很大帮助。
例如:您可以创建一个 MenuPolicy 文件,在其中放置菜单的所有 restrictions/authorazitions 逻辑
然后根据您的策略在菜单的 blade 文件中使用 @can 指令
检查那里
https://laravel.com/docs/5.6/authorization#creating-policies
我正在使用 laravel 5.5 为用户开发 基于角色的身份验证。 系统用户可以有多个角色,这些角色可以访问多个菜单。 我想检查用户的当前角色是否可以访问特定菜单。
以下是我的table结构
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
});
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->longText('description')->nullable();
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
});
Schema::create('role_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('role_id');
$table->integer('is_default')->default(0);
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')->on('roles')
->onDelete('cascade');
});
Schema::create('menus', function (Blueprint $table) {
$table->increments('id');
$table->integer('parent_id');
$table->string('name')->unique();
$table->string('action')->unique();
$table->integer('sequence');
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
});
Schema::create('menu_roles', function (Blueprint $table) {
$table->increments('id');
$table->integer('menu_id');
$table->integer('role_id');
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
$table->foreign('menu_id')
->references('id')->on('menus')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')->on('roles')
->onDelete('cascade');
});
我定义的关系如下:
User.php
public function roles()
{
return $this->belongsToMany(Role::class);
}
Role.php
public function users()
{
return $this->belongsToMany(User::class);
}
public function menus()
{
return $this->belongsToMany(Menu::class);
}
如何检查特定角色是否可以访问特定菜单?
提前致谢
您必须创建另一个枢轴 table,例如
Schema::create('role_menu', function (Blueprint $table) {
$table->increments('id');
$table->integer('menu_id');
$table->integer('role_id');
$table->foreign('menu_id')
->references('id')->on('menus')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')->on('roles')
->onDelete('cascade');
});
显然,必须有一个menus
table。
打开了很多可能性...我认为更好的方法是创建一个可用于特定菜单路由的中间件。
例如:
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Check user roles in order to check if role has access to the menu
foreach($request->user()->roles as $role) {
// This code supposes that your route is something like http://app.tld/menus/{menu_id}
if($role->menus()->find($request->route('menu_id'))) {
return $next($request);
}
}
// Otherwise abort, redirect.. whatever
abort(401);
}
假设您有一个像 $menuId
这样的变量,您可以简单地将 whereHas() 与经过身份验证的用户一起使用并检查关系是否存在:
$canAccess = auth()->user()->whereHas('roles.menus', function ($query) use($menuId) {
$query->where('id', $menuId);
})->exists();
您可以在用户和角色中进行检查...我会在用户模型中进行检查
像这样的东西应该在用户模型中工作...对于角色,只需删除与用户相关的表。
public function checkMenuPermission($key)
{
// YOUR KEY can be name, id, any unique column...
$results = DB::table('users')
->join('role_user', 'users.id', '=', 'role_user.user_id')
->join('menu_roles', 'role_user.role_id', '=', 'menu_roles.role_id')
->join('menus', 'menus.id', '=', 'menu_roles.menu_id')
->select('menus.name')
->where('users.id', $this->id)
->where('menus.name', $key)
->orderBy('menus.name')
->distinct()
->get()->count();
return $results > 0 ? true : false;
}
然后在你的控制器中就可以像 $user->checkMenuPermission('someSome');
编辑
如果你只想用 Eloquent 做,你可以
public function checkMenuPermission($key){
foreach($this->menus as $m){
if($m->name == $key){
return true;
}
}
return false;
}
你知道政策是如何运作的吗? 在这种情况下,它应该对您有很大帮助。 例如:您可以创建一个 MenuPolicy 文件,在其中放置菜单的所有 restrictions/authorazitions 逻辑 然后根据您的策略在菜单的 blade 文件中使用 @can 指令
检查那里 https://laravel.com/docs/5.6/authorization#creating-policies