ordermind/logical-permissions

提供支持基于数组的权限,具有逻辑门如AND和OR。

3.0.0-alpha6 2021-01-06 10:39 UTC

This package is auto-updated.

Last update: 2024-09-06 18:12:58 UTC


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',
  ],
]

在这个例子中,roleflag 是要评估的权限类型。为了使此示例正常工作,您需要根据之前的指南注册权限类型 '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