stonecoldtea / laravel-permission
Laravel 5.4及以上版本的权限处理
Requires
- php: >=7.0
- illuminate/auth: ~5.3.0|~5.4.0|~5.5.0
- illuminate/container: ~5.3.0|~5.4.0|~5.5.0
- illuminate/contracts: ~5.3.0|~5.4.0|~5.5.0
- illuminate/database: ~5.4.0|~5.5.0
Requires (Dev)
- monolog/monolog: ^1.22
- orchestra/testbench: ~3.3.0|~3.4.2|~3.5.0
- phpunit/phpunit: ^5.7|6.2
- dev-master
- 2.7.5
- 2.7.4
- 2.7.3
- 2.7.2
- 2.7.1
- 2.7.0
- 2.6.0
- 2.5.4
- 2.5.3
- 2.5.2
- 2.5.1
- 2.5.0
- 2.4.2
- 2.4.1
- 2.4.0
- 2.3.2
- 2.3.1
- 2.3.0
- 2.2.0
- 2.1.6
- 2.1.5
- 2.1.4
- 2.1.3
- 2.0.2
- 2.0.1
- 2.0.0
- v1.x-dev
- 1.13.0
- 1.12.0
- 1.11.1
- 1.11.0
- 1.10.0
- 1.9.0
- 1.8.0
- 1.7.0
- 1.6.1
- 1.6.0
- 1.5.3
- 1.5.2
- 1.5.1
- 1.5.0
- 1.4.0
- 1.3.4
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.1
- 1.2.0
- 1.1.0
- 1.0.2
- 1.0.1
- 1.0.0
- 0.0.1
- dev-analysis-XaEQ6Z
- dev-fix-guard-checks
This package is not auto-updated.
Last update: 2024-09-29 05:14:39 UTC
README
此包允许您在数据库中管理用户权限和角色。
安装后,您可以执行如下操作
// Adding permissions to a user $user->givePermissionTo('edit articles'); // Adding permissions via a role $user->assignRole('writer'); $role->givePermissionTo('edit articles');
如果您使用多个守卫,我们也为您考虑到了。每个守卫都将有自己的权限和角色集,可以分配给守卫的用户。请参阅readme中的使用多个守卫部分。
因为所有权限都将注册在Laravel的gate上,所以您可以使用Laravel的默认can函数测试用户是否有权限
$user->can('edit articles');
Spatie是比利时安特卫普的网页设计公司。您可以在我们的网站上找到我们所有开源项目的概述在这里。
安装
此包可用于Laravel 5.4或更高版本。如果您使用的是较旧的Laravel版本,请查看此包的v1分支。
您可以通过composer安装此包
composer require spatie/laravel-permission
在Laravel 5.5中,服务提供程序将自动注册。在框架的较旧版本中,只需将服务提供程序添加到config/app.php文件中即可
'providers' => [ // ... Spatie\Permission\PermissionServiceProvider::class, ];
您可以使用以下命令发布迁移
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"
迁移发布后,您可以通过运行迁移来创建角色和权限表
php artisan migrate
您可以使用以下命令发布配置文件
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"
发布后,config/permission.php配置文件包含
return [ 'models' => [ /* * When using the "HasRoles" trait from this package, we need to know which * Eloquent model should be used to retrieve your permissions. Of course, it * is often just the "Permission" model but you may use whatever you like. * * The model you want to use as a Permission model needs to implement the * `Spatie\Permission\Contracts\Permission` contract. */ 'permission' => Spatie\Permission\Models\Permission::class, /* * When using the "HasRoles" trait from this package, we need to know which * Eloquent model should be used to retrieve your roles. Of course, it * is often just the "Role" model but you may use whatever you like. * * The model you want to use as a Role model needs to implement the * `Spatie\Permission\Contracts\Role` contract. */ 'role' => Spatie\Permission\Models\Role::class, ], 'table_names' => [ /* * When using the "HasRoles" trait from this package, we need to know which * table should be used to retrieve your roles. We have chosen a basic * default value but you may easily change it to any table you like. */ 'roles' => 'roles', /* * When using the "HasRoles" trait from this package, we need to know which * table should be used to retrieve your permissions. We have chosen a basic * default value but you may easily change it to any table you like. */ 'permissions' => 'permissions', /* * When using the "HasRoles" trait from this package, we need to know which * table should be used to retrieve your models permissions. We have chosen a * basic default value but you may easily change it to any table you like. */ 'model_has_permissions' => 'model_has_permissions', /* * When using the "HasRoles" trait from this package, we need to know which * table should be used to retrieve your models roles. We have chosen a * basic default value but you may easily change it to any table you like. */ 'model_has_roles' => 'model_has_roles', /* * When using the "HasRoles" trait from this package, we need to know which * table should be used to retrieve your roles permissions. We have chosen a * basic default value but you may easily change it to any table you like. */ 'role_has_permissions' => 'role_has_permissions', ], /* * By default all permissions will be cached for 24 hours unless a permission or * role is updated. Then the cache will be flushed immediately. */ 'cache_expiration_time' => 60 * 24, /* * By default we'll make an entry in the application log when the permissions * could not be loaded. Normally this only occurs while installing the packages. * * If for some reason you want to disable that logging, set this value to false. */ 'log_registration_exception' => true, ];
用法
首先将Spatie\Permission\Traits\HasRoles特性添加到您的User模型中
use Illuminate\Foundation\Auth\User as Authenticatable; use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable { use HasRoles; // ... }
- 注意,如果您需要将
HasRoles特性与另一个模型(例如Page)一起使用,您还需要将protected $guard_name = 'web';也添加到该模型中,否则您会得到一个错误use Illuminate\Database\Eloquent\Model; use Spatie\Permission\Traits\HasRoles; class Page extends Model { use HasRoles; protected $guard_name = 'web'; // or whatever guard you want to use // ... }
此包允许用户与权限和角色相关联。每个角色都与多个权限相关联。一个Role和一个Permission是常规Eloquent模型。它们需要一个name,可以创建如下
use Spatie\Permission\Models\Role; use Spatie\Permission\Models\Permission; $role = Role::create(['name' => 'writer']); $permission = Permission::create(['name' => 'edit articles']);
如果您使用多个守卫,还需要设置guard_name属性。请参阅readme中的使用多个守卫部分。
HasRoles特性为您的模型添加了Eloquent关系,可以直接访问或用作基本查询
// get a list of all permissions directly assigned to the user $permissions = $user->permissions; // get all permissions inherited by the user via roles $permissions = $user->getAllPermissions(); // get a collection of all defined roles $roles = $user->getRoleNames(); // Returns a collection
HasRoles特性还为您添加了role作用域,以便将查询限定为某些角色或权限
$users = User::role('writer')->get(); // Returns only users with the role 'writer'
role作用域可以接受一个字符串,一个\Spatie\Permission\Models\Role对象或一个\Illuminate\Support\Collection对象。
相同的特性还添加了一个作用域,以仅获取具有特定权限的用户。
$users = User::permission('edit articles')->get(); // Returns only users with the permission 'edit articles' (inherited or directly)
作用域可以接受一个字符串,一个\Spatie\Permission\Models\Permission对象或一个\Illuminate\Support\Collection对象。
使用“直接”权限(以下说明如何使用角色和权限)
权限可以授予任何用户
$user->givePermissionTo('edit articles'); // You can also give multiple permission at once $user->givePermissionTo('edit articles', 'delete articles'); // You may also pass an array $user->givePermissionTo(['edit articles', 'delete articles']);
权限也可以从用户中撤销
$user->revokePermissionTo('edit articles');
或者一次性撤销并添加新的权限
$user->syncPermissions(['edit articles', 'delete articles']);
您可以测试用户是否拥有权限
$user->hasPermissionTo('edit articles');
...或者测试用户是否拥有多个权限
$user->hasAnyPermission(['edit articles', 'publish articles', 'unpublish articles']);
保存的权限将注册到默认守卫的Illuminate\Auth\Access\Gate类中。因此,您可以使用Laravel的默认can函数测试用户是否拥有权限
$user->can('edit articles');
通过角色使用权限
角色可以分配给任何用户
$user->assignRole('writer'); // You can also assign multiple roles at once $user->assignRole('writer', 'admin'); // or as an array $user->assignRole(['writer', 'admin']);
角色也可以从用户中移除
$user->removeRole('writer');
角色也可以进行同步
// All current roles will be removed from the user and replaced by the array given $user->syncRoles(['writer', 'admin']);
您可以确定用户是否具有特定的角色
$user->hasRole('writer');
您也可以确定用户是否具有给定列表中的任何角色
$user->hasAnyRole(Role::all());
您也可以确定用户是否具有给定列表中的所有角色
$user->hasAllRoles(Role::all());
assignRole、hasRole、hasAnyRole、hasAllRoles和removeRole函数可以接受字符串、\Spatie\Permission\Models\Role对象或\Illuminate\Support\Collection对象。
权限可以分配给角色
$role->givePermissionTo('edit articles');
您也可以确定角色是否具有特定的权限
$role->hasPermissionTo('edit articles');
权限也可以从角色中撤销
$role->revokePermissionTo('edit articles');
givePermissionTo和revokePermissionTo函数可以接受字符串或Spatie\Permission\Models\Permission对象。
权限会从角色自动继承。此外,也可以直接为用户分配单个权限。例如
$role = Role::findByName('writer'); $role->givePermissionTo('edit articles'); $user->assignRole('writer'); $user->givePermissionTo('delete articles');
在上面的示例中,一个角色被授予编辑文章的权限,并将此角色分配给一个用户。现在用户可以编辑文章,并且还可以删除文章。'删除文章'的权限是用户的直接权限,因为它直接分配给了他们。当我们调用$user->hasDirectPermission('delete articles')时,它返回true,但对于$user->hasDirectPermission('edit articles')返回false。
此方法在为应用程序中的角色和用户设置权限表单时非常有用,如果想要限制或更改用户的角色继承权限,即仅允许更改用户的直接权限。
您可以列出所有这些权限
// Direct permissions $user->getDirectPermissions() // Or $user->permissions; // Permissions inherited from the user's roles $user->getPermissionsViaRoles(); // All permissions which apply on the user (inherited and direct) $user->getAllPermissions();
所有这些响应都是Spatie\Permission\Models\Permission对象的集合。
如果我们遵循前面的示例,第一个响应将包含删除文章权限的集合,第二个将包含编辑文章权限的集合,第三个将包含两者。
使用Blade指令
此包还添加了Blade指令来验证当前登录用户是否具有给定列表中的所有或任何角色。
可选地,您可以作为第二个参数传递将执行检查的guard。
Blade和角色
测试特定角色
@role('writer') I am a writer! @else I am not a writer... @endrole
等同于
@hasrole('writer') I am a writer! @else I am not a writer... @endhasrole
测试列表中的任何角色
@hasanyrole($collectionOfRoles) I have one or more of these roles! @else I have none of these roles... @endhasanyrole // or @hasanyrole('writer|admin') I am either a writer or an admin or both! @else I have none of these roles... @endhasanyrole
测试所有角色
@hasallroles($collectionOfRoles) I have all of these roles! @else I do not have all of these roles... @endhasallroles // or @hasallroles('writer|admin') I am both a writer and an admin! @else I do not have all of these roles... @endhasallroles
Blade和权限
此包没有添加任何权限特定的Blade指令。相反,使用Laravel的本地@can指令来检查用户是否具有特定的权限。
@can('edit articles') // @endcan
或
@if(auth()->user()->can('edit articles') && $some_other_condition) // @endif
使用多个守卫
当使用默认的Laravel auth配置时,所有上述方法都将默认工作,无需额外配置。
然而,当使用多个守卫时,它们将充当权限和角色的命名空间。这意味着每个守卫都有自己的权限和角色集合,可以分配给其用户模型。
使用多个守卫的权限和角色
默认情况下,默认守卫(config('auth.default.guard'))将被用作新权限和角色的守卫。当为特定守卫创建权限和角色时,您必须在模型上指定其guard_name。
// Create a superadmin role for the admin users $role = Role::create(['guard_name' => 'admin', 'name' => 'superadmin']); // Define a `publish articles` permission for the admin users belonging to the admin guard $permission = Permission::create(['guard_name' => 'admin', 'name' => 'publish articles']); // Define a *different* `publish articles` permission for the regular users belonging to the web guard $permission = Permission::create(['guard_name' => 'web', 'name' => 'publish articles']);
检查用户是否具有特定守卫的权限
$user->hasPermissionTo('publish articles', 'admin');
将权限和角色分配给守卫用户
您可以使用与上述在 通过角色使用权限 中描述相同的方法来为用户分配权限和角色。只需确保权限或角色上的 guard_name 与用户的守卫相匹配,否则将抛出 GuardDoesNotMatch 异常。
使用具有多个守卫的 blade 指令
您可以通过将希望使用的守卫作为指令的第二个参数传入来使用 使用 blade 指令 中列出的所有 blade 指令。
@role('super-admin', 'admin') I am a super-admin! @else I am not a super-admin... @endrole
使用中间件
此包包含 RoleMiddleware 和 PermissionMiddleware 中间件。您可以将它们添加到您的 app/Http/Kernel.php 文件中。
protected $routeMiddleware = [ // ... 'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class, 'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class, ];
然后,您可以使用中间件规则来保护您的路由。
Route::group(['middleware' => ['role:super-admin']], function () { // }); Route::group(['middleware' => ['permission:publish articles']], function () { // }); Route::group(['middleware' => ['role:super-admin','permission:publish articles']], function () { // });
或者,您可以使用 |(管道)字符将多个角色或权限分开。
Route::group(['middleware' => ['role:super-admin|writer']], function () { // }); Route::group(['middleware' => ['permission:publish articles|edit articles']], function () { // });
您可以通过在构造函数中设置所需的中间件类似地保护控制器。
public function __construct() { $this->middleware(['role:super-admin','permission:publish articles|edit articles']); }
使用 artisan 命令
您可以使用 artisan 命令从控制台创建角色或权限。
php artisan permission:create-role writer
php artisan permission:create-permission 'edit articles'
当为特定守卫创建权限和角色时,您可以指定守卫名称作为第二个参数。
php artisan permission:create-role writer web
php artisan permission:create-permission 'edit articles' web
单元测试
在您的应用程序测试中,如果您不是在测试的 setUp() 部分中将角色和权限作为种子,那么您可能会遇到一个“先有鸡还是先有蛋”的情况,即角色和权限没有注册到门(因为您的测试是在门注册之后创建它们的)。解决这个问题很简单:在您的测试中,只需添加一个 setUp() 指令重新注册权限,如下所示
public function setUp() { // first include all the normal setUp operations parent::setUp(); // now re-register all the roles and permissions $this->app->make(\Spatie\Permission\PermissionRegistrar::class)->registerPermissions(); }
数据库种子
关于数据库种子的两个注意事项
-
在种子之前最好清除
spatie.permission.cache,以避免缓存冲突错误。这可以通过 Artisan 命令(见后面的“故障排除:缓存部分”)或直接在种子类中完成(见下面的示例)。 -
以下是一个示例种子,它清除缓存,创建权限,然后将权限分配给角色
use Illuminate\Database\Seeder; use Spatie\Permission\Models\Role; use Spatie\Permission\Models\Permission; class RolesAndPermissionsSeeder extends Seeder { public function run() { // Reset cached roles and permissions app()['cache']->forget('spatie.permission.cache'); // create permissions Permission::create(['name' => 'edit articles']); Permission::create(['name' => 'delete articles']); Permission::create(['name' => 'publish articles']); Permission::create(['name' => 'unpublish articles']); // create roles and assign existing permissions $role = Role::create(['name' => 'writer']); $role->givePermissionTo('edit articles'); $role->givePermissionTo('delete articles'); $role = Role::create(['name' => 'admin']); $role->givePermissionTo('publish articles'); $role->givePermissionTo('unpublish articles'); } }
扩展
如果您需要扩展或替换现有的 Role 或 Permission 模型,您只需注意以下几点
- 您的
Role模型需要实现Spatie\Permission\Contracts\Role接口 - 您的
Permission模型需要实现Spatie\Permission\Contracts\Permission接口 - 您可以使用此命令发布配置
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"
并且更新 models.role 和 models.permission 的值
缓存
角色和权限数据被缓存以提高性能。
当您使用提供的用于操作角色和权限的方法时,缓存将自动为您重置
$user->assignRole('writer'); $user->removeRole('writer'); $user->syncRoles(params); $role->givePermissionTo('edit articles'); $role->revokePermissionTo('edit articles'); $role->syncPermissions(params);
但是,如果您直接在数据库中操作权限/角色数据而不是调用提供的方法,那么除非您手动重置缓存,否则您将看不到应用程序中的更改。
手动重置缓存
要手动重置此包的缓存,请运行
php artisan cache:forget spatie.permission.cache
缓存标识符
提示:如果您正在使用缓存服务(如 redis 或 memcached),并且服务器上运行着其他网站,您可能会遇到缓存冲突。在 /config/cache.php 中设置您自己的缓存 prefix 是明智的,使其对每个应用程序都是唯一的。这将防止其他应用程序意外地使用/更改您的缓存数据。
需要 UI 吗?
此包不包含任何屏幕,您需要自己构建。要开始,请查看 此详细教程,由 Caleb Oki 提供。
测试
composer test
更新日志
请参阅CHANGELOG以获取有关最近更改的更多信息。
贡献
有关详细信息,请参阅CONTRIBUTING。
安全
如果您发现任何与安全相关的问题,请通过电子邮件发送至freek@spatie.be,而不是使用问题跟踪器。
明信片软件
您可以使用此软件包,但如果它进入您的生产环境,我们非常欢迎您从家乡给我们寄一张明信片,提及您正在使用我们的哪个软件包。
我们的地址是:Spatie,Samberstraat 69D,2060 安特卫普,比利时。
我们将在我们的公司网站上发布收到的所有明信片。
致谢
此软件包主要基于Jeffrey Way的出色Laracasts课程,关于权限和角色。他的原始代码可以在GitHub上的此仓库中找到。
特别感谢Alex Vanderbist对v2的巨大帮助,以及感谢Chris Brown长期支持我们维护该软件包。
资源
替代方案
Povilas Korop在Laravel News的文章中列出了替代方案。在这篇文章中,他还比较了laravel-permission与Joseph Silber的Bouncer,在我们看来,这也是一个出色的软件包。
支持我们
Spatie是一家位于比利时安特卫普的网页设计公司。您可以在我们的网站上找到我们所有开源项目的概述。
您的业务依赖于我们的贡献吗?请联系我们,在Patreon上支持我们。所有承诺都将专门用于分配人力进行维护和开发新功能。
许可
MIT许可证(MIT)。请参阅许可文件以获取更多信息。