Entrust是一个Laravel扩展包,用于在Laravel应用中实现RBAC(Role-Based Access Control)权限管理
使用 Entrust 扩展包在 Laravel 5 中实现 RBAC 权限管理(一):安装配置篇
1、安装Voyager
Voyager是一个Laravel后台管理扩展包,关于其介绍请参考:http://laravelacademy.org/post/6401.html,由于Voyager也自带了角色功能,这会导致在执行安装命令(voyager:install)的时候报错(roles表重复),所以我们需要对Voyager的安装步骤作调整,将voyager:install
拆解成多个步骤。
如果还没有执行make:auth
的话,先运行这个命令快速生成用户认证所需文件和配置:
php artisan make:auth
发布Voyager所需前端资源文件、配置文件及数据库相关文件:
php artisan vendor:publish --provider=TCG\Voyager\VoyagerServiceProvider
php artisan vendor:publish --provider=Intervention\Image\ImageServiceProviderLaravel5
执行完这一步之后去database/migrations
目录下删除*_create_user_roles_table.php
和*_create_roles_table.php
,然后到database/seeds
目录下修改RolesTableSeeder.php
文件如下:
用填充类database/seeds/UsersTableSeeder.php
中设置的邮箱和密码进行登录,登录成功后会跳转到一个异常页面,这是因为Voyager路由中使用了中间件admin.user
,该中间件中使用的用户实例是TCG\Voyager\Models\User
,该模型类中使用的角色与用户对应关系表是Voyager提供的user_roles
,而我们在之前的安装过程中将这个数据表迁移文件删除了,取而代之的,我们使用的是Entrust提供的role_user
表,所以这里我们需要将用户实例修改为App\User
,这样就能正常访问http://academycms.dev/admin
了:

接下来我们主要的文章都要做在Roles这个菜单(http://academycms.dev/admin/roles
)里面:
使用 Entrust 扩展包在 Laravel 5 中实现 RBAC 权限管理(二):基本使用篇
1、创建角色/权限并进行分配
首先我们来创建Role
和Permission
:
$owner = new Role(); $owner->name = \'owner\'; $owner->display_name = \'Project Owner\'; $owner->description = \'User is the owner of a given project\'; $owner->save(); $admin = new Role(); $admin->name = \'admin\'; $admin->display_name = \'User Administrator\'; $admin->description = \'User is allowed to manage and edit other users\'; $admin->save();
接下来我们将创建的两个roles分配给用户:
$user = User::where(\'username\', \'=\', \'michele\')->first(); //调用EntrustUserTrait提供的attachRole方法 $user->attachRole($admin); // 参数可以是Role对象,数组或id // 或者也可以使用Eloquent原生的方法 $user->roles()->attach($admin->id); //只需传递id即可
现在我们还需要添加相应权限到这些角色上:
$createPost = new Permission(); $createPost->name = \'create-post\'; $createPost->display_name = \'Create Posts\'; $createPost->description = \'create new blog posts\'; $createPost->save(); $editUser = new Permission(); $editUser->name = \'edit-user\'; $editUser->display_name = \'Edit Users\'; $editUser->description = \'edit existing users\'; $editUser->save(); $owner->attachPermission($createPost); //等价于 $owner->perms()->sync(array($createPost->id)); $admin->attachPermissions(array($createPost, $editUser)); //等价于 $admin->perms()->sync(array($createPost->id, $editUser->id));
2、检查角色&权限
完成上述操作后,下面我们可以检查相应角色和权限:
$user->hasRole(\'owner\'); // false $user->hasRole(\'admin\'); // true $user->can(\'edit-user\'); // true $user->can(\'create-post\'); // true
hasRole()
和can
都可以接收数组形式的角色和权限进行检查:
$user->hasRole([\'owner\', \'admin\']); // true $user->can([\'edit-user\', \'create-post\']); // true
默认情况下,如果用户拥有以上任意一个角色或权限都会返回true
,如果你想检查用户是否拥有所有角色及权限,可以传递true
作为第二个参数到相应方法:
$user->hasRole([\'owner\', \'admin\']); // true $user->hasRole([\'owner\', \'admin\'], true); // false $user->can([\'edit-user\', \'create-post\']); // true $user->can([\'edit-user\', \'create-post\'], true); // false
用户可以拥有多个角色。
除此之外,还可以通过Entrust
门面检查当前登录用户是否拥有指定角色和权限:
Entrust::hasRole(\'role-name\'); Entrust::can(\'permission-name\');
甚至还可以通过通配符的方式来检查用户权限:
// match any admin permission $user->can("admin.*"); // true // match any permission about users $user->can("*_users"); // true
3、ability方法
还可以通过使用ability
方法来实现更加高级的检查,这需要三个参数(角色、权限、选项),同样角色和权限既可以是字符串也可以是数组:
$user->ability(array(\'admin\', \'owner\'), array(\'create-post\', \'edit-user\')); // 或者 $user->ability(\'admin,owner\', \'create-post,edit-user\');
这将会检查用户是否拥有任意提供的角色和权限,在本例中会返回true
,因为用户的角色是admin
并且拥有create-post
权限。
第三个参数是一个可选数组:
$options = array( \'validate_all\' => true | false (Default: false), \'return_type\' => boolean | array | both (Default: boolean) );
其中validate_all
是一个布尔值,用于设置是否检查所有值;return_type
用于指定返回布尔值、检查值数组还是两者都有。
下面是一个输出示例:
$options = array( \'validate_all\' => true, \'return_type\' => \'both\' ); list($validate, $allValidations) = $user->ability( array(\'admin\', \'owner\'), array(\'create-post\', \'edit-user\'), $options ); var_dump($validate); // bool(false) var_dump($allValidations); // array(4) { // [\'role\'] => bool(true) // [\'role_2\'] => bool(false) // [\'create-post\'] => bool(true) // [\'edit-user\'] => bool(false) // }
同样,Entrust
门面也为当前登录用户提供了ability
方法:
Entrust::ability(\'admin,owner\', \'create-post,edit-user\'); // 等价于 Auth::user()->ability(\'admin,owner\', \'create-post,edit-user\');
4、Blade模板
在Blade模板中也可以使用上述三个方法对应的指令:
@role(\'admin\')
This is visible to users with the admin role. Gets translated to \Entrust::role(\’admin\’)
@endrole @permission(\'manage-admins\')
This is visible to users with the given permissions. Gets translated to \Entrust::can(\’manage-admins\’). The @can directive is already taken by core laravel authorization package, hence the @permission directive instead.
@endpermission @ability(\'admin,owner\', \'create-post,edit-user\')
This is visible to users with the given abilities. Gets translated to \Entrust::ability(\’admin,owner\’, \’create-post,edit-user\’)
@endability
5、中间件
你可以在中间件中通过角色或权限来过滤路由以及路由群组:
Route::group([\'prefix\' => \'admin\', \'middleware\' => [\'role:admin\']], function() { Route::get(\'/\', \'AdminController@welcome\'); Route::get(\'/manage\', [ \'middleware\' => [\'permission:manage-admins\'], \'uses\' => \'AdminController@manageAdmins\' ]); });
支持OR/AND逻辑:
\'middleware\' => [\'role:admin|root\'] \'middleware\' => [\'permission:owner\', \'permission:writer\']
同样可以使用ability
中间件:
\'middleware\' => [\'ability:admin|owner,create-post|edit-user,true\']
6、路由过滤器的快捷实现
通过权限和角色过滤路由你还可以在app/Http/routes.php
调用如下代码:
// 只有拥有\'create-post\'权限对应角色的用户才能访问admin/post* Entrust::routeNeedsPermission(\'admin/post*\', \'create-post\'); // 只有所有者才能访问admin/advanced* Entrust::routeNeedsRole(\'admin/advanced*\', \'owner\'); // 第二个参数可以是数组,这样用户必须满足所有条件才能访问对应路由 Entrust::routeNeedsPermission(\'admin/post*\', array(\'create-post\', \'edit-comment\')); Entrust::routeNeedsRole(\'admin/advanced*\', array(\'owner\',\'writer\'));
以上方法都可以接受第三个参数,如果第三个参数为空那么禁止访问默认调用App::abort(403)
,否则会返回第三个参数,所以我们可以这么做:
Entrust::routeNeedsRole(\'admin/advanced*\', \'owner\', Redirect::to(\'/home\'));
甚至还可以接受第四个参数,该参数默认为true
,意味着将会检查提供的所有角色和权限,如果你将其设置为false
,则该方法只有在所有角色/权限都不满足才会返回失败:
// 如果用户拥有\'create-post\'、\'edit-comment\'其中之一或者两个权限都具备则可以访问 Entrust::routeNeedsPermission(\'admin/post*\', array(\'create-post\', \'edit-comment\'), null, false); // 如果用户是所有者、作者或者都具备则可以访问 Entrust::routeNeedsRole(\'admin/advanced*\', array(\'owner\',\'writer\'), null, false); Entrust::routeNeedsRoleOrPermission( \'admin/advanced*\', array(\'owner\', \'writer\'), array(\'create-post\', \'edit-comment\'), null, false );
7、路由过滤器
Entrust角色/权限可通过调用Entrust
门面上的can
和hasRole
方法应用在过滤器中:
Route::filter(\'manage_posts\', function() { // check the current user if (!Entrust::can(\'create-post\')) { return Redirect::to(\'admin\'); } }); // 只有用户对应角色拥有 \'manage_posts\' 权限才能访问任意 admin/post 路由 Route::when(\'admin/post*\', \'manage_posts\');
使用过滤器来检查角色:
Route::filter(\'owner_role\', function() { // check the current user if (!Entrust::hasRole(\'Owner\')) { App::abort(403); } }); // 只有所有者才能访问 admin/advanced* 路由 Route::when(\'admin/advanced*\', \'owner_role\');
正如你所看到的,Entrust::hasRole
和Entrust::can
方法检查用户是否登录、然后才去判断他们是否有用指定角色或权限,如果用户没有登录则直接返回false
。
如果想要查看在Laravel 5.2中基于Entrust实现后台权限管理的实例可参考Ryan的这个Github项目:https://github.com/yuansir/laravel5-rbac-example
原文: Laravel学院 http://laravelacademy.org/post/6613.html
转载请注明:拈花古佛 » Voyager 后台管理系统中集成 Entrust