针对用户不同角色的基于角色的身份验证

时间:2018-08-21 10:07:25

标签: laravel laravel-5.5

我使用的是laravel 5.5,正在为用户开发基于角色的身份验证。 系统用户可以具有多个角色,并且那些角色可以访问多个菜单。 我想检查用户的当前角色是否可以访问特定菜单。

以下是我的表结构

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);
}

如何检查特定角色是否可以访问特定菜单?

预先感谢

4 个答案:

答案 0 :(得分:1)

您可以在User(用户)和Role(角色)中进行检查...我会在User Model(用户模型)中进行

类似的事情应该在用户模型中起作用……对于角色,只需删除与用户相关的表即可。

List<SubItems>

然后在您的控制器中只能像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');

答案 1 :(得分:0)

假设您有一个像$menuId这样的变量,您可以简单地将whereHas()与经过身份验证的用户一起使用,并检查关系是否存在:

$canAccess = auth()->user()->whereHas('roles.menus', function ($query) use($menuId) {

    $query->where('id', $menuId);

})->exists();

答案 2 :(得分:0)

您知道政策如何运作吗? 在这种情况下,它应该对您有很大帮助。 例如:您可以创建一个MenuPolicy文件,在其中放置菜单的所有限制/授权逻辑 然后只需根据您的策略在菜单的刀片文件中使用 @can 指令

检查那里 https://laravel.com/docs/5.6/authorization#creating-policies

答案 3 :(得分:-1)

您必须创建另一个数据透视表,例如

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表。

打开了很多可能性...我认为更好的方法是创建一个可用于特定菜单路线的中间件。

例如:

/**
 * 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);
}