梦想还是要有的, 万一实现了呢?

Voyager 后台管理系统中集成 Entrust

PHP 拈花古佛 8862℃ 0评论 繁體

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了:

Voyager 后台管理系统中集成 Entrust

接下来我们主要的文章都要做在Roles这个菜单(http://academycms.dev/admin/roles)里面:

Voyager 后台管理系统中集成 Entrust

使用 Entrust 扩展包在 Laravel 5 中实现 RBAC 权限管理(二):基本使用篇

1、创建角色/权限并进行分配

首先我们来创建RolePermission

$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门面上的canhasRole方法应用在过滤器中:

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::hasRoleEntrust::can方法检查用户是否登录、然后才去判断他们是否有用指定角色或权限,如果用户没有登录则直接返回false

如果想要查看在Laravel 5.2中基于Entrust实现后台权限管理的实例可参考Ryan的这个Github项目:https://github.com/yuansir/laravel5-rbac-example

原文:  Laravel学院 http://laravelacademy.org/post/6613.html

转载请注明:拈花古佛 » Voyager 后台管理系统中集成 Entrust

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址