Entrust - Laravel 5 用户角色权限

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.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,874评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,151评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,270评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,137评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,116评论 5 370
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,935评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,261评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,895评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,342评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,854评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,978评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,609评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,181评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,182评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,402评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,376评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,677评论 2 344

推荐阅读更多精彩内容