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.