Study Notes

Entrust - Laravel 5 用户角色权限

2016-07-04  本文已影响6473人  ZhouJiping

Entrust 是一个基于role-permission 的用户权限组件

安装Laravel 5 Entrust

"zizaco/entrust": "5.2.x-dev"

注册服务

Zizaco\Entrust\EntrustServiceProvider::class,

添加门面

 'Entrust'   => Zizaco\Entrust\EntrustFacade::class,

添加中间件,app/Http/Kernel.php 中的routeMiddleware数组中

    'role' => \Zizaco\Entrust\Middleware\EntrustRole::class,
    'permission' => \Zizaco\Entrust\Middleware\EntrustPermission::class,
    'ability' => \Zizaco\Entrust\Middleware\EntrustAbility::class,

配置
设置config/auth.php属性,entrust会指向这里面的表和模型

也可以使用

php artisan vendor:publish

User relation to roles

生成migration(<timestamp>_entrust_setup_tables.php)文件

php artisan entrust:migration

生成的表

roles — 用户角色
permissions — 用户权限
role_user — 角色和user多对多的关系
permission_role — 权限和角色的多对多关系

模型层

Role

<?php 

namespace App;

use Zizaco\Entrust\EntrustRole;

class Role extends EntrustRole
{
}

字段介绍

name - 角色的唯一名字,用来显示用的,如:管理员,中美管理员,普通用户,认证用户,。。。

display_name: 给人看的角色名,可选
display_name: 对角色更加详细的描述,可选

Permission Model

<?php namespace App;

use Zizaco\Entrust\EntrustPermission;

class Permission extends EntrustPermission
{
}

name: examples: create-post,
display_name: 给人看的显示的名字
description: 更详细的信息:The permission display_name allows a user to description."

User Model

<?php

use Zizaco\Entrust\Traits\EntrustUserTrait;

class User extends Eloquent
{
    use EntrustUserTrait; // add this trait to your user model

    ...
}

trait中的方法 roles(), hasRole($name), can($permission), ability($role, $permissions, $options)

软删除

role_user, role_permission 的外键在更新和删除的时候都适用了级联操作, onDelete('cascade')
onUpdate('cascade),

为保持数据库的完整性,使用onDelete('cascade')
onUpdate('cascade),当该中间表的父级表发生删除或者更新的时候,中间表的记录也会跟着改变。

用法

先来测试下:

$owner = new Role();
$owner->name         = 'owner';
$owner->display_name = 'Project Owner'; // optional
$owner->description  = 'User is the owner of a given project'; // optional
$owner->save();

$admin = new Role();
$admin->name         = 'admin';
$admin->display_name = 'User Administrator'; // optional
$admin->description  = 'User is allowed to manage and edit other users'; // optional
$admin->save();

给用户添加角色

$user = User::where('username', '=', 'michele')->first();

// role attach alias
$user->attachRole($admin); // parameter can be an Role object, array, or id

// or eloquent's original technique
$user->roles()->attach($admin->id); // id only

给角色添加权限

$createPost = new Permission();
$createPost->name         = 'create-post';
$createPost->display_name = 'Create Posts'; // optional
// Allow a user to...
$createPost->description  = 'create new blog posts'; // optional
$createPost->save();

$editUser = new Permission();
$editUser->name         = 'edit-user';
$editUser->display_name = 'Edit Users'; // optional
// Allow a user to...
$editUser->description  = 'edit existing users'; // optional
$editUser->save();

$admin->attachPermission($createPost);
// equivalent to $admin->perms()->sync(array($createPost->id));

$owner->attachPermissions(array($createPost, $editUser));
// equivalent to $owner->perms()->sync(array($createPost->id, $editUser->id));

检查用户是否有Roles和Permissions的权限

$user->hasRole('owner');   // false
$user->hasRole('admin');   // true
$user->can('edit-user');   // false
$user->can('create-post'); // true
$user->hasRole(['owner', 'admin']);       // true
$user->can(['edit-user', 'create-post']); // true

查看目前登录用户的权限

Entrust::hasRole('role-name');
Entrust::can('permission-name');

等于 

Auth::user()->hasRole('role-name');
Auth::user()->can('permission-name);

还可以使用匹配

// match any admin permission
$user->can("admin.*"); // true

// match any permission about users
$user->can("*_users"); // true

User ability

有三个参数,parameters (roles, permissions, options)
其中:roles: 检查用户是否具有角色
permissions: 检查用户是否具有权限

如果不设置第三个参数,只要roles,和permission中匹配任何一个,都返回true.

写法如下:

$user->ability(array('admin', 'owner'), array('create-post', 'edit-user'));

// or

$user->ability('admin,owner', 'create-post,edit-user');

$user->ability的意思是,只要用户具有ability参数中的任何一条,就返回true, 当用户没有参数内任何一条权限和角色时,返回false

第三个参数 options

$options = array(
    'validate_all' => true | false (Default: false),
    'return_type'  => boolean | array | both (Default: boolean)
);

validate_all: 设置为true, 则需要匹配所有的ability中的roles值和permission值,设置为false,则只要roles和permission中有一个任何一个值匹配都能返回true

return_type: 返回boolean的true或false, 或者返回具体roles和permission具体每一个值的true或false的数组, 或者用both, 前面的两个都要返回。

自测试:

 $user->ability('admin,owner', 'create-post,edit-user', ['validate_all' => false, 'return_type' => 'boolean']);

//  返回 
true


>>> $user->ability('admin,owner', 'create-post,edit-user', ['validate_all' => true, 'return_type' => 'boolean']);
=> false

>>> $user->ability('admin,owner', 'create-post,edit-user', ['validate_all' => true, 'return_type' => 'array']);
=> [
     "roles" => [
       "admin" => true,
       "owner" => false,
     ],
     "permissions" => [
       "create-post" => true,
       "edit-user" => false,
     ],
   ]

>>> $user->ability('admin,owner', 'create-post,edit-user', ['validate_all' => true, 'return_type' => 'both']);
=> [
     false,
     [
       "roles" => [
         "admin" => true,
         "owner" => false,
       ],
       "permissions" => [
         "create-post" => true,
         "edit-user" => false,
       ],
     ],
   ]
>>> 

可以用:
list($validate, $allValidations) = $user->ability(
    array('admin', 'owner'),
    array('create-post', 'edit-user'),
    $options
);

当前用户用ability():

Entrust::ability('admin,owner', 'create-post,edit-user');

或者用

Auth::user()->ability('admin,owner', 'create-post,edit-user'); // 建议用这个

模版上的使用 有三个命令

@role('admin')
    <p>This is visible to users with the admin role. Gets translated to 
    \Entrust::role('admin')</p>
@endrole

@permission('manage-admins')
    <p>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.</p>
@endpermission

@ability('admin,owner', 'create-post,edit-user')
    <p>This is visible to users with the given abilities. Gets translated to 
    \Entrust::ability('admin,owner', 'create-post,edit-user')</p>
@endability

使用middleware

Route::group(['prefix' => 'admin', 'middleware' => ['role:admin']], function() {
    Route::get('/', 'AdminController@welcome');
    Route::get('/manage', ['middleware' => ['permission:manage-admins'], 'uses' => 'AdminController@manageAdmins']);
});

中间件中使用“或者”
'middleware' => ['role:admin|root']

admin 或者 root 权限都能进入

中间件的与 and 操作:

'middleware' => ['permission:owner', 'permission:writer']

路由过滤

// only users with roles that have the 'manage_posts' permission will be able to access any route within admin/post
Entrust::routeNeedsPermission('admin/post*', 'create-post');

// only owners will have access to routes within admin/advanced
Entrust::routeNeedsRole('admin/advanced*', 'owner');

// optionally the second parameter can be an array of permissions or roles
// user would need to match all roles or permissions for that route
Entrust::routeNeedsPermission('admin/post*', array('create-post', 'edit-comment'));
Entrust::routeNeedsRole('admin/advanced*', array('owner','writer'));

上面的方法都可以接受第三个参数,跳转链接

如果不写第三个参数,不允许的用户会被阻止进入,并返回abort(403)的错误,如果设置了第三个参数,如下:

Entrust::routeNeedsRole('admin/advanced*', 'owner', Redirect::to('/home'));

如果用户没有这么权限,那么就会跳转到/home的页面

进一步来说,上面这些函数还可以接受第四个参数,值为true 或 false, 默认是true,代表用户需要符合所有的角色和权限,如果设置成false,那么只要有一个符合就能进入

// if a user has 'create-post', 'edit-comment', or both they will have access
Entrust::routeNeedsPermission('admin/post*', array('create-post', 'edit-comment'), null, false);

// if a user is a member of 'owner', 'writer', or both they will have access
Entrust::routeNeedsRole('admin/advanced*', array('owner','writer'), null, false);

// if a user is a member of 'owner', 'writer', or both, or user has 'create-post', 'edit-comment' they will have access
// if the 4th parameter is true then the user must be a member of Role and must have Permission
Entrust::routeNeedsRoleOrPermission(
    'admin/advanced*',
    array('owner', 'writer'),
    array('create-post', 'edit-comment'),
    null,
    false
);

Route filter

Route::filter('manage_posts', function()
{
    // check the current user
    if (!Entrust::can('create-post')) {
        return Redirect::to('admin');
    }
});

// only users with roles that have the 'manage_posts' permission will be able to access any admin/post route
Route::when('admin/post*', 'manage_posts');

两个可能会出现的错误

If you encounter an error when doing the migration that looks like:

SQLSTATE[HY000]: General error: 1005 Can't create table 'laravelbootstrapstarter.#sql-42c_f8' (errno: 150)
(SQL: alter table role_user add constraint role_user_user_id_foreign foreign key (user_id)
references users (id)) (Bindings: array ())
Then it's likely that the id column in your user table does not match the user_id column in role_user. Make sure both are INT(10).

When trying to use the EntrustUserTrait methods, you encounter the error which looks like

Class name must be a valid object or a string
then probably you don't have published Entrust assets or something went wrong when you did it. First of all check that you have the entrust.php file in your app/config directory. If you don't, then try php artisan vendor:publish and, if it does not appear, manually copy the /vendor/zizaco/entrust/src/config/config.php file in your config directory and rename it entrust.php.

上一篇下一篇

猜你喜欢

热点阅读