saeven/zf3-circlical-user

Laminas的完整用户实体、权限和访问模块

0.3.2 2023-06-13 17:31 UTC

README

Codacy Badge Codacy Badge Latest Stable Version Total Downloads Quality Gate Status Gitter

Laminas的即插即用认证、角色、资源和操作控制。

快速安装

  • 基于cookie的认证(使用halite及其认证加密)
  • 基于角色的访问控制(RBAC),在控制器和操作级别设置守卫
  • 基于用户的访问控制,补充RBAC
  • 基于资源的权限,在角色和用户级别提供“资源”和“动词”控制,例如(所有管理员都可以“添加”服务器,只有Pete可以“删除”)

您可以在这个可用的骨架中看到它的实际应用。

消息

当然,市场上也有其他的认证、ACL和用户模块。这个模块提供了对Doctrine的原生支持,只需插入您的用户实体即可使用。

认证使用cookie持久化,这意味着根本不需要使用会话。我开发的环境中更倾向于这种方式,例如在EC2自动扩展组中对会话管理进行复杂的或容易出错的解决方案。

最后,使用备受信任的Halite进行认证加密,使用PHP的新密码函数进行密码哈希。在r/php上总是寻求反馈。在r/php上寻求反馈。如果您像我一样是个偏执狂,这个库应该会很好地满足您的需求!

这个库基于拒绝优先原则。以下定义的所有内容都是“允许”授权。

用户认证

该模块提供了从用户级别开始的完整身份/认证管理。设计目标是将此与注册或登录过程连接起来,只需要一行代码。

登录

验证提交的登录表单,然后执行以下操作以允许用户通过

$user = $this->auth()->authenticate( $emailOrUsername, $password );

认证成功,将生成满足后续身份检索的cookie。

注销

销毁cookie并使用此命令重新生成该用户的会话密钥

 $this->auth()->clearIdentity();

可插拔拒绝策略

有人试图做他们不应该做的事情?使用可插拔的DenyStrategy很容易控制会发生什么。创建一个实现DenyStrategyInterface的类并将其插入到您的配置中。此模块提供了一个默认的RedirectStrategy,如果问题是缺少认证且不是XHTTP请求,则会将用户发送到登录页面。易于使用,您可以这样配置

'deny_strategy' => [

    'class' => \CirclicalUser\Strategy\RedirectStrategy::class,

    'options' => [
        'controller' => \Application\Controller\LoginController::class,
        'action' => 'index',
    ],
],

编写自己的应该非常简单,请参阅提供的测试。

可插拔密码强度检查器

您可以通过取消注释password_strength_checker配置键来使用内置的paragonie/passwdqc支持。如果您有更复杂的需求,也可以自己实现;取消注释键并指定自己的PasswordCheckerInterface实现。这将在接收到弱密码输入时抛出WeakPasswordExceptions。

密码检查器的配置可以有两种方式

无选项的类

'password_strength_checker' => \CirclicalUser\Service\PasswordChecker\Passwdqc::class,

带选项的类

'password_strength_checker' => [
    'implementation' => \CirclicalUser\Service\PasswordChecker\Zxcvbn::class,
    'config' => [
        'required_strength' => 3,
    ],
],

为您的用户创建访问权限

您的应用程序需要修改以为每个用户创建一个独特的认证记录。这非常简单。

创建和认证

在用户注册流程中,你可能需要创建记录并登录用户。为此,你可以使用AccessService的辅助工具或'create'方法。

从控制器中,你可以使用auth插件

 $this->auth()->create(User $user, string $usernameOrEmail, string $password); // controller helper

或者,AuthenticationService

$container->get(AuthenticationService::class)->create($user, $usernameOrEmail, $password);

仅创建

否则,如果你想仅创建用户认证记录而不登录,请使用

$container->get(AuthenticationService::class)->registerAuthenticationRecord(User $user, string $username, string $password)

角色

用户属于数据库中配置的层次结构角色。默认的访客用户是无组的。
角色用于限制对控制器操作资源的访问。

守卫

守卫是针对控制器 & 操作 -- 或 中间件 -- 的条件,用于检查用户权限以允许/拒绝尝试访问。它的工作方式与BjyAuthorize(我使用多年的一个很好的模块)非常相似。

配置守卫非常简单。你的模块配置可能如下所示

 return [
    'circlical' => [
        'user' => [
            'guards' => [
                'ModuleName' => [
                    "controllers" => [
                        \Application\Controller\IndexController::class => [
                            'default' => [], // anyone can access
                        ],
                        \Application\Controller\MemberController::class => [
                            'default' => ['user'], // specific role access
                        ],
                        \Application\Controller\AdminController::class => [
                            'default' => ['admin'],
                            'actions' => [  // action-level guards
                                'list' => [ 'user' ], // role 'user' can access 'listAction' on AdminController
                            ],
                        ],
                        \Application\Controller\ComplexController::class => [
                            'default' => ['user'],
                            'actions' => [  // action-level guards
                                'save' => [
                                    AccessService::GUARD_ACTION => 'save',      // you can lean on action/resource rules as well
                                    AccessService::GUARD_RESOURCE => 'complex', // which call 'isAllowed' on AccessService
                                ],
                                'delete' => [
                                    AccessService::GUARD_ROLE => 'admin',       // it is also possible to override the role requirement
                                    AccessService::GUARD_ACTION => 'save',
                                    AccessService::GUARD_RESOURCE => 'complex',
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ],
    ],
 ];   

如果你正在定义对中间件路由定义的访问,则不需要配置上面的'actions'部分。此外,该模块被忽略,因此你可以将你的中间件处理器的类放在任何模块中;例如

 return [
    'circlical' => [
        'user' => [
            'guards' => [
                'Middleware' => [
                    "controllers" => [
                        \Application\Middleware\MiddlewareHandler::class => [
                            'default' => [], // anyone can access
                        ],
                    ],
                ],
            ],
        ],
    ],
 ];  

资源 & 权限

资源可以是

这两种用法在控制器中都是有效的

$this->auth()->isAllowed('door','open');

或对象

// server implements ResourceInterface
$server = $serverMapper->get(142);
$this->auth()->isAllowed($server,'shutdown');

AccessService也可以以类似的方式使用。有关更多用法示例,请参阅AccessService测试

通过AccessService授予一个角色一个权限

用户权限

你还可以给个别用户,访问特定资源上的特定操作的权限。这个库提供了Doctrine实体和一个映射器来实现这一点 -- 但你可以非常容易地连接你自己的UserPermissionProviderInterface。简而言之,这允许AccessService使用已认证的用户来确定登录的个人是否可以执行超过其角色权限的任何操作。用户权限意味着更宽松,而不是限制性。

用户API令牌

此模块还提供了一个生成UserApiToken对象的实用程序。有关用法,请参阅测试。

将此实体的映射添加到您的用户实体中非常简单

/**
 * @ORM\OneToMany(targetEntity="CirclicalUser\Entity\UserApiToken", mappedBy="user");
 */
private $api_tokens;

使用UserApiTokenMapper获取令牌以执行自己的逻辑,例如

$token = $this->userApiTokenMapper->get('d0cad39b-f269-405e-b3f9-d45b349c0587');

当它被使用/消耗时,你可以对其进行标记

$token->tagUse();

作用域(由你的应用程序定义)使用位标志定义

$token->addScope(FooApi::SCOPE_QUERY);

Cookie安全

你可以通过调整auth/secure_cookies配置值来配置你的cookie是否应该设置安全标志为'true'。如果需要在服务器上运行发现方法,例如,检查当前请求是否通过SSL,则该值接受布尔值或闭包。

安装

Composer调优

此包的依赖链依赖于doctrine/doctrine-module,它反过来又依赖于laminas/laminas-cache

laminas 缓存以奇怪的方式连接,可能会尝试安装大量的问题适配器(取决于您的 PHP 版本)。建议您使用 composer 的 replace 功能,将这种混乱排除在您的应用程序之外,如下所示

  "replace": {    
    "laminas/laminas-cache-storage-adapter-apc": "*",
    "laminas/laminas-cache-storage-adapter-apcu": "*",
    "laminas/laminas-cache-storage-adapter-blackhole": "*",
    "laminas/laminas-cache-storage-adapter-dba": "*",
    "laminas/laminas-cache-storage-adapter-ext-mongodb": "*",
    "laminas/laminas-cache-storage-adapter-filesystem": "*",
    "laminas/laminas-cache-storage-adapter-memcache": "*",
    "laminas/laminas-cache-storage-adapter-memcached": "*",
    "laminas/laminas-cache-storage-adapter-mongodb": "*",
    "laminas/laminas-cache-storage-adapter-redis": "*",
    "laminas/laminas-cache-storage-adapter-session": "*",
    "laminas/laminas-cache-storage-adapter-wincache": "*",
    "laminas/laminas-cache-storage-adapter-xcache": "*",
    "laminas/laminas-cache-storage-adapter-zend-server": "*",
  },

此外,由于您正在使用这个库,您可能没有使用 laminas/laminas-authentication,这个库也是由 doctrine-module 安装的。您可以将以下行添加到您的 replace 块中

"laminas/laminas-authentication": "*",