bishwopl/zf3-circlical-user

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

v2.0.1 2020-10-24 08:53 UTC

README

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

为 Laminas 提供即插即用的身份验证、角色、资源和行为控制。

快速安装

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

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

Missive

当然,市面上有其他身份验证、访问控制列表(ACL)和用户模块。此模块内置对 Doctrine 的支持,只需插入您的用户实体即可使用。

身份验证使用 cookie 持久化,这意味着根本不需要使用会话。我之所以这样做,是因为我开发的环境需要这种偏好,例如在 EC2 自动扩展组上不需要复杂或容易出错的问题管理会话。

最后,使用受信任的 Halite 处理认证加密,使用 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 上的“创建”方法。

从控制器中,您可以使用认证插件

 $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
                            ],
                        ],
                    ],
                ],
            ],
        ],
    ],
 ];   

如果您正在定义针对中间件路由定义的访问,则不需要配置上面的“操作”部分。进一步地,该模块将被忽略,因此您可以将您的中间件处理器的类放在任何模块中;例如

 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": "*",