目录
一、安装laravel-permissions扩展
#不指定安装版本的命令
composer require spatie/laravel-permission
#指定安装版本的命令
composer require "spatie/laravel-permission:~2.7"
说明:~2.7是安装的版本,因为需要根据框架的版本选择permission扩展的版本(根据个人框架版本来选择。我安装的是2.7版本)
二、生成数据库迁移文件
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"
执行完生成迁移文件命令,就会在
\database\migrations
目录下,生成一个以
_create_permission_tables.php
结尾的文件。
三、执行数据迁移
php artisan migrate
如果MySQL版本低,执行完命令就会报错,错误如下
意思就是
:MySQL版本低,列的字段长度太长。
解决方法
:修改app里的providers里的AppServiceProvider.php文件
\Schema::defaultStringLength(191);
再次执行:
php artisan migrate 命令即可
四、php artisan migrate 生成的表
- 首先是用户表(users)都是一些基本用户信息包括名字、邮箱、密码什么的。
- 权限表(permissions)权限表就是存放所有权限的一张表,权限可以是控制器访问权限,接口访问权限,model访问权限。
- 角色表(roles)角色表就是存放你所有的角色。
- 用户权限表(model_has_permissions)这张表记录的就是model_id,permission_id的多对多的关系表,用户直接获取权限。
- 用户角色表(model_has_roles)这张表记录的用户拥有的角色,表里有model_id,role_id这个也是记录用户和角色多对多的关系表。
- 角色权限表(role_has_permissions)这张表记录的是角色拥有哪些权限,表里就2个字段role_id,permission_id,也可以根据需要进行拓展!
五、生成配置信息
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"
会在
config
目录下生成一个:permission.php文件
六、permission.php 文件的使用和说明
return [
'models' => [
/**
* @TODO 当使用这个包中的“HasPermissions”特性时,我们需要知道应该使用哪个Eloquent模型来检索您的权限。
* 当然,它通常只是“许可”模式,但你可以使用任何你喜欢的。
* 要用作权限模型的模型需要实现“Spatie\Permission\Contracts\Permission”契约。
*/
'permission' => Spatie\Permission\Models\Permission::class,
/**
* @TODO 当使用这个包中的“HasRoles”特性时,我们需要知道应该使用哪个Eloquent模型来检索角色。
* 当然,它通常只是“角色”模型,但你可以使用任何你喜欢的。
* 要用作角色模型的模型需要实现“Spatie\Permission\Contracts\Role”契约。
*/
'role' => Spatie\Permission\Models\Role::class,],
'table_names' => [
/**
* @TODO 当使用这个包中的“HasRoles”特性时,我们需要知道是哪个表应该用于检索角色。
* 我们选择了一种基本的默认值,但您可以很容易地将其更改为任何您喜欢的表。
*/
'roles' => 'roles',
/**
* @TODO 当使用这个包中的“HasPermissions”特性时,我们需要知道是哪个表应用于检索您的权限。
* 我们选择了一种基本的默认值,但您可以很容易地将其更改为任何您喜欢的表。
*/
'permissions' => 'permissions',
/**
* @TODO 当使用这个包中的“HasPermissions”特性时,我们需要知道是哪个表应该用于检索您的模型权限。
* 我们选择了基本的默认值,但您可以轻松地将其更改为任何您喜欢的表。
*/
'model_has_permissions' => 'model_has_permissions',
/**
* @TODO 当使用这个包中的“HasRoles”特性时,我们需要知道是哪个表应该用于检索模型角色。
* 我们选择了基本的默认值,但您可以轻松地将其更改为任何您喜欢的表。
*/
'model_has_roles' => 'model_has_roles',
/**
* @TODO 当使用这个包中的“HasRoles”特性时,我们需要知道是哪个表应该用于检索角色权限。
* 我们选择了基本的默认值,但您可以轻松地将其更改为任何您喜欢的表。
*/
'role_has_permissions' => 'role_has_permissions',
],
'column_names' => [
/*
* @ TODO 如果您希望将相关的模型主键命名为`model_id`.
* 例如,如果您的主键都是uuid,这就很好了。在这种情况下,将其命名为`model_uuid`.
*/
'model_morph_key' => 'model_id',
],
/**
* @TODO 当设置为true时,所需的权限/角色名称将添加到异常中消息。
* 在某些情况下,这可以被认为是信息泄露,所以为了最佳的安全性,这里的默认设置为false。
*/
'display_permission_in_exception' => false,
'cache' => [
/**
* @TODO 默认情况下,所有权限都会缓存24小时,以提高性能。当权限或角色更新时,缓存会自动刷新。
*/
'expiration_time' => \DateInterval::createFromDateString('24 hours'),
/**
* @TODO 用于存储所有权限的缓存键。
*/
'key' => 'spatie.permission.cache',
/**
* @TODO 当通过传递permission来检查模型的权限时实例,则此键确定Permissions模型上的哪个属性用于缓存。
* 理想情况下,这应该匹配您首选的检查权限的方式,例如:`$user->can('view-posts')` 应该是 'name'.
*/
'model_key' => 'name',
/**
* @TODO 您可以选择使用cache.php配置文件中列出的任何“store”驱动程序来指定特定的缓存驱动程序用于权限和角色缓存。
* 这里使用'default'意味着使用cache.php中的'default'设置。
*/
'store' => 'default',
],
];
七、在user模型下加载角色相关信息
use HasRoles;
八、测试角色、权限
#新建一个控制器
php artisan make:controller IndexController
控制器的内容如下:
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use phpDocumentor\Reflection\Types\Self_;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Traits\HasRoles;
class IndexController extends Controller
{
public function index()
{
//@TODO 自己测试的时候,根据步骤从上到下执行每个方法即可
//添加用户、添加角色、添加权限
//self::addUserRolePermission();
//给用户添加角色
//self::userAddRole();
//给角色添加权限
//self::roleAddPermission();
//给用户添加权限
self::userAddPermission();
}
//测试:添加测试用户、添加测试角色、添加测试权限
private static function addUserRolePermission()
{
$userData = [
['name' => '张三', 'mobile' => '13666666666', 'password' => '123',],
['name' => '李四', 'mobile' => '13888888888', 'password' => '123',],
];
//添加用户
$userInfo = User::insert( $userData );
//添加角色
$roleData = [
['name' => '作家',],
['name' => '读者'],
];
foreach($roleData as $roleValue){
$role = Role::create( $roleValue );
}
//添加权限
$permissionData = [
['name' => '新增文章'],
['name' => '编辑文章'],
['name' => '查看文章'],
['name' => '删除文章'],
];
foreach($permissionData as $permissionValue){
$permission = Permission::create( $permissionValue );
}
echo 'ok';
die;
}
//测试:给用户添加角色
private static function userAddRole()
{
//执行完此步骤,表[model_has_roles]会多一条数据,model_type=App\User:就代表是用户 role_id:角色id model_id:用户id
$user = User::find( 1 );
$res = $user->assignRole( '作家' );
print_r( $res );
}
//测试:给角色添加权限
private static function roleAddPermission()
{
/**
* 第一种方式:给角色添加权限 @TODO 每次添加一个权限
* 执行完此步骤,表[role_has_permission]会多一条数据,permission_id:权限id role_id:角色id
* 给作家添加[新增文章权限]
*/
$role = Role::find( 1 );
//$res = $role->givePermissionTo('新增文章');
//print_r($res);die;
/**
* 第二种方式:将权限分给角色 @TODO 每次给角色添加一个权限
* 给作家添加[查看文章]
*/
$permission = Permission::find( 2 );
//$res = $permission->assignRole($role);
//print_r($res);die;
/**
* 第三种方式:将多个权限同步到一个角色
* 给作家添加[查看文章 和 删除文章 权限]
* @TODO syncPermissions 该方法会覆盖掉角色之前所有的权限
*/
$permission = Permission::whereIn( 'id', [1, 2] )->get();
$allPermission = $role->syncPermissions( $permission );
}
//测试:给用户添加权限
private static function userAddPermission()
{
//执行完此步骤,表[model_has_permission]会多一条数据,model_type=App\User:就代表是用户
$user = User::find( 1 );
$addUserPermission = $user->givePermissionTo( '新增文章' );
print_r( $addUserPermission );
}
}
九、有关用户、角色、权限方法的使用
/**
* 第一个方法 从缓存中获取所有权限 @TODO 'spatie.permission.cache' 这个key是固定的。
*/
$cachePermission = Cache::get('spatie.permission.cache');
/**
* 第二个方法 从角色中删除权限:方式1(通过角色删除)
*/
$role = Role::find(1);
$deleteRes = $role->revokePermissionTo('查看文章');
print_r($deleteRes->toArray());
//从角色中删除权限:方式2(通过权限删除)
$permission = Permission::find(4);
$deleteRes = $permission->removeRole($role);
print_r($deleteRes->toArray());
$user = User::find( 1 );
//获取某个用户的所有权限
$permissions = $user->permissions;
print_r($permissions->toArray());
//获取用户通过角色继承的所有权限
$permissions = $user->getAllPermissions();
print_r($permissions->toArray());
//获取某个用户的所有角色
$roles = $user->getRoleNames();
print_r($roles);
/**
* @TODO 特征(trait)还为您的模型添加了一个“角色”范围,以便将查询范围限定为某些角色或权限
*/
//仅返回具有角色 '作家' 的用户
$user = User::role( '作家' )->get();
print_r($user->toArray());
//仅返回具有 '新增文章'(继承或直接)权限的用户
$user = User::permission( '新增文章' )->get();
print_r($user->toArray());
//可以撤销用户权限
$user->revokePermissionTo('新增文章');
//或者一次性撤消并添加新的权限
$user->syncPermissions(['新增文章', '删除文章']);
//测试用户是否拥有权限
$user->hasPermissionTo('新增文章');
//或者可以传递一个代表权限 ID 的整数
$user->hasPermissionTo(1);
$user->hasPermissionTo(Permission::find(1)->id);
$user->hasPermissionTo($somePermission->id);
//同时校验用户是否拥有多个权限(通过权限 名称 校验)
$user->hasAnyPermission(['新增文章', '编辑文章', '删除文章']);
//同时校验用户是否同时拥有多个权限(通过权限 ID 校验)
$user->hasAnyPermission(['新增文章', 2, 4]);
//校验用户是否具有某个角色
$user->hasRole('作家');
//还可以确定用户是否具有任何给定的角色列表
$user->hasAnyRole(Role::all());
//还可以确定用户是否具有所有给定的角色列表
$user->hasAllRoles(Role::all());
//可以给角色一个许可
$role->givePermissionTo('编辑文章');
//确定角色是否具有某种权限
$role->hasPermissionTo('编辑文章');
//角色撤销权限
$role->revokePermissionTo('编辑文章');
//权限是从角色自动继承的。 当让,个人权限也可以分配给用户
$role = Role::findByName('作家');
$role->givePermissionTo('编辑文章');
$user->assignRole('作家');
$user->givePermissionTo('删除文章');
在上面的示例中,角色被授予编辑文章的权限,并且该角色被分配给用户。
现在,用户可以编辑文章并删除文章。 ‘删除文章’ 的权限是用户的直接许可,因为它直接分配给他们。
当我们调用 $user->hasDirectPermission('删除文章') 时,它会返回 true
而对 $user->hasDirectPermission('编辑文章') 返回 false。
//如果你为应用程序中的角色和用户构建权限并希望限制或更改用户角色的继承权限(即仅允许更改用户的直接权限),则此方法非常有用。
//直接权限
$user->getDirectPermissions(); 或者使用 $user->permissions
//从用户角色继承的权限
$user->getPermissionsViaRoles();
//适用于用户的所有权限(继承和直接)
$user->getAllPermissions();
所有这些响应都是 Spatie\Permission\Models\Permission 对象的集合。
十、权限中间件的使用
laravel-permission扩展附带
RoleMiddleware
和
PermissionMiddleware
中间件。 你可以将它们添加到你的
app/Http/Kernel.php
文件中。
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
然后,你可以使用中间件规则保护你的路由:
#例如
Route::group(['middleware' => ['role:super-admin']], function () { // });
Route::group(['middleware' => ['permission:删除文章']], function () { // });
Route::group(['middleware' => ['role:super-admin','permission:删除文章']], function () { // });
或者,您可以用 |(管道)字符分隔多个角色或权限
Route::group(['middleware' => ['role:super-admin|作家']], function () { // });
Route::group(['middleware' => ['permission:新增文章|编辑文章']], function () { // });
通过在构造函数中设置所需的中间件,可以同样保护您的控制器
public function __construct()
{
$this->middleware( ['role:超级管理员', 'permission:删除文章|编辑文章'] );
}
十一、使用 artisan 命令操作权限
可以使用 artisan 命令从控制台创建角色或权限
php artisan permission:create-role 作家
php artisan permission:create-permission "新增文章"
在为特定守卫创建权限和角色时,可以将守卫名称指定为第二个参数
php artisan permission:create-role 作家 web
php artisan permission:create-permission "新增文章" web
十二、权限缓存的使用
当你使用提供的方法来操作角色和权限时,缓存会自动为您重置
$user->assignRole('作家');
$user->removeRole('作家');
$user->syncRoles(params);
$role->givePermissionTo('编辑文章');
$role->revokePermissionTo('编辑文章');
$role->syncPermissions(params);
$permission->assignRole('作家');
$permission->removeRole('作家');
$permission->syncRoles(params);
但是,如果直接在数据库中操作“权限/角色”数据而不是调用提供的方法,则除非手动重置缓存,否则不会在应用程序中看到反映的更改。
要手动重置此软件包的缓存,请运行:
php artisan cache:forget spatie.permission.cache