基于角色的Laravel许可

Use*_*Cat 10 php laravel

我正在尝试在Laravel应用程序中执行基于角色的权限控制.我想检查一些用户可以执行哪些操作,但我无法弄清楚如何在我的模型中实现门和策略(权限描述在数据库中,并且是与存储资源的ID的表相关联的布尔值).

这是我使用的数据库模型:

图

我想知道laravel gate在我的情况下是否有用,我如何实现它,如果没有,如何制作一个基本的中间件来处理权限控制以保护路由(或控制器).

在表资源中,我有一个标识资源的uuid,别名是资源的名称,并且具有动作的点符号值或资源的上下文(例如'mysystem.users.create','mysystem.roles.delete ','mysystem.users.images.view').策略表有一个布尔"允许"字段,用于描述用户的权限.

提前致谢.

ker*_*rin 11

这是我使用策略在Laravel中实现基于角色的权限的方式.

用户可以拥有多个角色.角色具有关联权限.每个权限都允许对特定模型执行特定操作.

迁移

角色表

class CreateRolesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name')->unique();
            $table->string('label');
            $table->text('description');
            $table->timestamps();
        });
    }
// rest of migration file
Run Code Online (Sandbox Code Playgroud)

权限表

class CreatePermissionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('permissions', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name')->unique();
            $table->string('label');
            $table->text('description');
            $table->timestamps();
        });
    }
// rest of migration file
Run Code Online (Sandbox Code Playgroud)

权限角色数据透视表

class CreatePermissionRolePivotTable  extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('permission_role', function (Blueprint $table) {
            $table->integer('permission_id')->unsigned()->index();
            $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');
            $table->integer('role_id')->unsigned()->index();
            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
            $table->primary(['permission_id', 'role_id']);
        });
    }
// rest of migration file
Run Code Online (Sandbox Code Playgroud)

角色用户数据透视表

class CreateRoleUserPivotTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('role_user', function (Blueprint $table) {
            $table->integer('role_id')->unsigned()->index();
            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
            $table->integer('user_id')->unsigned()->index();
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->primary(['role_id', 'user_id']);
        });
    }
// rest of migration file
Run Code Online (Sandbox Code Playgroud)

楷模

用户

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

public function assignRole(Role $role)
    {
        return $this->roles()->save($role);
    }

public function hasRole($role)
    {
        if (is_string($role)) {
            return $this->roles->contains('name', $role);
        }
        return !! $role->intersect($this->roles)->count();
    }
Run Code Online (Sandbox Code Playgroud)

角色

class Role extends Model
{
    protected $guarded = ['id'];
    protected $fillable = array('name', 'label', 'description');
    public function permissions()
    {
        return $this->belongsToMany(Permission::class);
    }
    public function givePermissionTo(Permission $permission)
    {
        return $this->permissions()->save($permission);
    }
    /**
     * Determine if the user may perform the given permission.
     *
     * @param  Permission $permission
     * @return boolean
     */
    public function hasPermission(Permission $permission, User $user)
    {
        return $this->hasRole($permission->roles);
    }
    /**
     * Determine if the role has the given permission.
     *
     * @param  mixed $permission
     * @return boolean
     */
    public function inRole($permission)
    {
        if (is_string($permission)) {
            return $this->permissions->contains('name', $permission);
        }
        return !! $permission->intersect($this->permissions)->count();
    }
}
Run Code Online (Sandbox Code Playgroud)

允许

class Permission extends Model
{
    protected $guarded = ['id'];
    protected $fillable = array('name', 'label', 'description');
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
    /**
     * Determine if the permission belongs to the role.
     *
     * @param  mixed $role
     * @return boolean
     */
    public function inRole($role)
    {
        if (is_string($role)) {
            return $this->roles->contains('name', $role);
        }
        return !! $role->intersect($this->roles)->count();
    }
}
Run Code Online (Sandbox Code Playgroud)

政策

每个模型都需要一个策略.以下是模型的示例策略item.该策略定义了四个操作的视图,创建,更新,删除的"规则".

class ItemPolicy
{
    use HandlesAuthorization;
    /**
     * Determine whether the user can view the item.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function view(User $user)
    {
        $permission = Permission::where('name', 'items-view')->first();
        return $user->hasRole($permission->roles);
    }
    /**
     * Determine whether the user can create items.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        $permission = Permission::where('name', 'items-create')->first();
        return $user->hasRole($permission->roles);
    }
    /**
     * Determine whether the user can update the item.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function update(User $user)
    {
        $permission = Permission::where('name', 'items-update')->first();
        return $user->hasRole($permission->roles);
    }
    /**
     * Determine whether the user can delete the item.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function delete(User $user)
    {
        $permission = Permission::where('name', 'items-delete')->first();
        return $user->hasRole($permission->roles);
    }
}
Run Code Online (Sandbox Code Playgroud)

注册每个政策 AuthServiceProvider.php

use App\Item;
use App\Policies\ItemPolicy;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        Item::class => ItemPolicy::class,
    ];
// rest of file
Run Code Online (Sandbox Code Playgroud)

控制器

在每个控制器中,请参阅策略中的相应授权操作.

例如,在以下index方法中ItemController:

public function index()
{
    $this->authorize('view', Item::class);

    $items = Item::orderBy('name', 'asc')->get();

    return view('items', ['items' => $items]);
}
Run Code Online (Sandbox Code Playgroud)

查看

在您的视图中,您可以检查用户是否具有特定角色:

@if (Auth::user()->hasRole('item-administrator'))
// do stuff
@endif
Run Code Online (Sandbox Code Playgroud)

或者如果需要特定许可:

@can('create', App\User::class)
// do stuff
@endcan
Run Code Online (Sandbox Code Playgroud)


web*_*Dev 4

回答您的问题如何制作一个基本的中间件来负责权限控制以保护路由(或控制器)?

只是一个例子:
这是您的路由的简单角色中间件
AdminRole

namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;
use Closure;

class AdminRole
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if(Auth::user()->role->name!=="admin"){ //Check your users' role or permission, in my case only admin role for routes
            return redirect('/access-denied');
        }
        return $next($request);
    }
}
Run Code Online (Sandbox Code Playgroud)

定义此中间件后将kernel.php文件更新为

protected $routeMiddleware = [
    ..............
    'admin' =>\App\Http\Middleware\AdminRole::class,
    ...................
];
Run Code Online (Sandbox Code Playgroud)

并使用此路由中间件:
使用路由中间件有不同的方法,但以下是一个示例

Route::group(['middleware' => ['auth','admin']], function () {
    Route::get('/', 'AdminController@index')->name('admin');
});
Run Code Online (Sandbox Code Playgroud)

注意: laravel 上有一些用于角色和权限的工具和库,但上面是创建基本路由中间件的示例。