ordermind / logical-permissions
提供支持基于数组的权限,具有逻辑门如AND和OR。
Requires
- php: ^7.4
- ordermind/logic-gates: ^1.3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.16
- phpmd/phpmd: ^2.8
- phpspec/prophecy: ^1.9
- phpspec/prophecy-phpunit: ^2.0
- phpstan/phpstan: ^0.12.19
- phpunit/phpunit: ^9.3
- squizlabs/php_codesniffer: ^3.5
README
logical-permissions
这是一个通用的库,提供支持基于数组的权限,包括AND和OR等逻辑门。您可以注册任何类型的权限,如角色和标志。这个库的目的是成为一个超灵活的基础,可以被任何框架使用。支持的PHP版本是5.6或更高。
入门指南
安装
composer require ordermind/logical-permissions
使用
注册权限类型
权限类型用于检查不同类型的访问控制条件,首先需要创建一个并注册。例如,如果我们想根据当前用户的角色确定访问权限,首先创建一个实现 Ordermind\LogicalPermissions\PermissionTypeInterface 的类,如下所示
use Ordermind\LogicalPermissions\PermissionTypeInterface; class MyPermissionType implements PermissionTypeInterface { public static function getName() { return 'role'; } public function checkPermission($role, $context) { $access = FALSE; if(!empty($context['user']['roles'])) { $access = in_array($role, $context['user']['roles']); } return $access; } }
现在我们已经实现了两个必需的方法 - getName() 和 checkPermission() - 并创建了一个简单的例子来检查用户的角色。权限类型的名称将被用作权限树中的键,而 checkPermission() 方法是检查当前用户是否具有角色的地方。
一旦创建了权限类型,可以像这样注册
use Ordermind\LogicalPermissions\AccessChecker; $permissionType = new MyPermissionType(); $accessChecker = new AccessChecker(); $permissionTypeCollection = $accessChecker->getPermissionTypeCollection(); $permissionTypeCollection->add($permissionType);
检查访问权限
现在一切设置好了,可以根据用户的角色检查他们的访问权限
$permissions = [ 'role' => 'admin', // The key 'role' here is the name of your permission type ]; $user = ['roles' => ['admin', 'sales']]; $access = $accessChecker->checkAccess($permissions, ['user' => $user]); // TRUE
权限树
在前面的例子中,有一个名为 $permissions 的变量,其外观如下
$permissions = [ 'role' => 'admin', ];
这是一个 权限树 的例子。权限树是一组按顺序评估的权限组合,用于确定特定动作的访问权限。例如,如果你想限制更新用户的访问权限,只想让具有 "admin" 角色的用户能够更新任何用户,但用户也应该能够更新自己的用户数据(至少是部分数据)。使用这个库提供的格式,这些条件可以优雅地表示为如下权限树
[ 'OR' => [ 'role' => 'admin', 'flag' => 'is_author', ], ]
在这个例子中,role 和 flag 是要评估的权限类型。为了使此示例正常工作,您需要根据之前的指南注册权限类型 'role' 和 'flag'。
绕过访问检查
这个库还支持绕过超级用户的完全访问检查的规则。为了使用此功能,首先需要创建一个实现 Ordermind\LogicalPermissions\BypassAccessCheckerInterface 的类,如下所示
use Ordermind\LogicalPermissions\BypassAccessCheckerInterface; class MyBypassAccessChecker implements BypassAccessCheckerInterface { public function checkBypassAccess($context) { $bypassAccess = FALSE; if($context['user']['id'] == 1) { $bypassAccess = TRUE; } return $bypassAccess; } }
然后可以像这样注册它
$bypassAccessChecker = new MyBypassAccessChecker(); $accessChecker->setBypassAccessChecker($bypassAccessChecker);
从现在起,每次调用 $accessChecker->checkAccess() 时,ID为1的用户将被豁免,无论权限如何,他们都将始终被授予访问权限。如果您想设置例外,可以在权限树的第一个级别添加 'NO_BYPASS' => TRUE。您甚至可以使用权限作为 NO_BYPASS 的条件。
示例
//Disallow access bypassing [ 'NO_BYPASS' => TRUE, 'role' => 'editor', ]
//Disallow access bypassing only if the user is an admin [ 'NO_BYPASS' => [ 'role' => 'admin', ], 'role' => 'editor', ]
逻辑门
当前支持的逻辑门有与门、与非门、或门、或非门、异或门和非门。您可以将逻辑门放置在权限树中的任何位置,并随心所欲地进行嵌套。所有逻辑门只支持数组作为它们的值,除了非门有特殊规则。如果值数组的键不是逻辑门,则假定它是或门。
与门
逻辑与门在其所有子项都返回true时返回true。否则返回false。
示例
//Allow access only if the user is both an editor and a sales person [ 'role' => [ 'AND' => ['editor', 'sales'], ], ]
//Allow access if the user is both a sales person and the author of the document [ 'AND' => [ 'role' => 'sales', 'flag' => 'is_author', ], ]
与非门
逻辑与非门在其子项之一或多个返回false时返回true。否则返回false。
示例
//Allow access by anyone except if the user is both an editor and a sales person [ 'role' => [ 'NAND' => ['editor', 'sales'], ], ]
//Allow access by anyone, but not if the user is both a sales person and the author of the document. [ 'NAND' => [ 'role' => 'sales', 'flag' => 'is_author', ], ]
或门
逻辑或门在其子项之一或多个返回true时返回true。否则返回false。
示例
//Allow access if the user is either an editor or a sales person, or both. [ 'role' => [ 'OR' => ['editor', 'sales'], ], ]
//Allow access if the user is either a sales person or the author of the document, or both [ 'OR' => [ 'role' => 'sales', 'flag' => 'is_author', ], ]
简写或
如前所述,任何没有逻辑门作为键的值数组都被解释为属于或门。
换句话说,这个权限树
[ 'role' => ['editor', 'sales'], ]
的解析方式与这个权限树
[ 'role' => [ 'OR' => ['editor', 'sales'], ], ]
或非门
逻辑或非门在其所有子项都返回false时返回true。否则返回false。
示例
//Allow access if the user is neither an editor nor a sales person [ 'role' => [ 'NOR' => ['editor', 'sales'], ], ]
//Allow neither sales people nor the author of the document to access it [ 'NOR' => [ 'role' => 'sales', 'flag' => 'is_author', ], ]
异或门
逻辑异或门在其子项之一或多个返回true且一个或多个子项返回false时返回true。否则返回false。异或门在其值数组中需要至少两个元素。
示例
//Allow access if the user is either an editor or a sales person, but not both [ 'role' => [ 'XOR' => ['editor', 'sales'], ], ]
//Allow either sales people or the author of the document to access it, but not if the user is both a sales person and the author [ 'XOR' => [ 'role' => 'sales', 'flag' => 'is_author', ], ]
非门
逻辑非门在其子项返回false时返回true,反之亦然。非门是特殊的,因为它支持字符串或单个元素的数组作为其值。
示例
//Allow access for anyone except editors [ 'role' => [ 'NOT' => 'editor', ], ]
//Allow access for anyone except the author of the document [ 'NOT' => [ 'flag' => 'is_author', ], ]
布尔权限
布尔权限是一种特殊的权限。它们可以用来允许或拒绝所有人的访问(除了有绕过访问权限的人)。它们不允许作为权限类型的后代,并且可能不包含子项。支持true布尔值以及表示为大写字符串的布尔值。当然,允许所有人访问的更简单方法是根本不为该操作定义任何权限,但有时可能需要明确允许所有人访问。
示例
//Allow access for anyone [ TRUE, ] //Using a boolean without an array is also permitted TRUE
//Example with string representation [ 'TRUE', ] //Using a string representation without an array is also permitted 'TRUE'
//Deny access for everyone except those with bypass access [ FALSE, ] //Using a boolean without an array is also permitted FALSE
//Example with string representation [ 'FALSE', ] //Using a string representation without an array is also permitted 'FALSE'
//Deny access for everyone including those with bypass access [ FALSE, 'NO_BYPASS' => TRUE, ]
API 文档
目录
AccessChecker
根据已注册的权限类型、权限树和上下文检查访问权限。
- 全名:\Ordermind\LogicalPermissions\AccessChecker
- 此类实现了:\Ordermind\LogicalPermissions\AccessCheckerInterface
setPermissionTypeCollection
设置权限类型集合。
AccessChecker::setPermissionTypeCollection( \Ordermind\LogicalPermissions\PermissionTypeCollectionInterface $permissionTypeCollection ): \Ordermind\LogicalPermissions\AccessCheckerInterface
参数
getPermissionTypeCollection
获取权限类型集合。
AccessChecker::getPermissionTypeCollection( ): \Ordermind\LogicalPermissions\PermissionTypeCollectionInterface|NULL
setBypassAccessChecker
设置绕过访问检查器。
AccessChecker::setBypassAccessChecker( \Ordermind\LogicalPermissions\BypassAccessCheckerInterface $bypassAccessChecker ): \Ordermind\LogicalPermissions\AccessCheckerInterface
参数
getBypassAccessChecker
获取绕过访问检查器。
AccessChecker::getBypassAccessChecker( ): \Ordermind\LogicalPermissions\BypassAccessCheckerInterface|NULL
getValidPermissionKeys
获取可以用于权限树的所有键。
AccessChecker::getValidPermissionKeys( ): array
返回值
有效的权限键。
checkAccess
检查权限树的访问权限。
AccessChecker::checkAccess( array|string|boolean $permissions, array|object|NULL $context = NULL, boolean $allowBypass = TRUE ): boolean
参数
返回值
如果访问被允许则返回TRUE,如果访问被拒绝则返回FALSE。
PermissionTypeCollection
权限类型集合。
- 全名:\Ordermind\LogicalPermissions\PermissionTypeCollection
- 此类实现了:\Ordermind\LogicalPermissions\PermissionTypeCollectionInterface
add
向集合中添加权限类型。
PermissionTypeCollection::add( \Ordermind\LogicalPermissions\PermissionTypeInterface $permissionType, boolean $overwriteIfExists = FALSE ): \Ordermind\LogicalPermissions\PermissionTypeCollectionInterface
参数
remove
从集合中按名称移除权限类型。如果权限类型在集合中找不到,则不执行任何操作。
PermissionTypeCollection::remove( string $name ): \Ordermind\LogicalPermissions\PermissionTypeCollectionInterface
参数
has
检查集合中是否存在权限类型。
PermissionTypeCollection::has( string $name ): boolean
参数
get
通过名称获取权限类型。如果找不到权限类型,则返回NULL。
PermissionTypeCollection::get( string $name ): \Ordermind\LogicalPermissions\PermissionTypeInterface|NULL
参数
toArray
返回该集合的PHP数组表示形式。
PermissionTypeCollection::toArray( ): array