yiisoft/user

方便的用户身份管理和访问检查

2.2.0 2024-05-07 07:31 UTC

This package is auto-updated.

Last update: 2024-09-14 09:28:21 UTC


README

Yii

Yii 用户


Latest Stable Version Total Downloads Build status Code Coverage Mutation testing badge static analysis type-coverage

此包处理与用户相关的功能

  • 登录和登出。
  • 获取当前登录身份。
  • 更改当前身份。
  • 检查当前用户的访问权限。
  • 基于请求属性的身份自动登录。
  • 基于请求cookie的自动登录或“记住我”。

需求

  • PHP 8.1 或更高版本。
  • JSON PHP 扩展。

安装

可以使用 Composer 安装此包

composer require yiisoft/user

通用用法

此包是 yiisoft/auth 的补充,并提供了与用户身份交互的附加功能。

处理身份

CurrentUser 类负责登录和登出,以及提供有关当前用户身份的数据。

/** 
 * @var \Psr\EventDispatcher\EventDispatcherInterface $eventDispatcher
 * @var \Yiisoft\Auth\IdentityRepositoryInterface $identityRepository
 */

$currentUser = new \Yiisoft\User\CurrentUser($identityRepository, $eventDispatcher);

如果用户尚未登录,则当前用户是访客

$currentUser->getIdentity(); // \Yiisoft\User\Guest\GuestIdentity instance
$currentUser->getId(); // null
$currentUser->isGuest(); // bool

如果您需要使用自定义身份类来表示访客用户,则在创建 CurrentUser 时应将 GuestIdentityFactoryInterface 实例作为第三个可选参数传递

/** 
 * @var \Psr\EventDispatcher\EventDispatcherInterface $eventDispatcher
 * @var \Yiisoft\Auth\IdentityRepositoryInterface $identityRepository
 * @var \Yiisoft\User\Guest\GuestIdentityFactoryInterface $guestIdentityFactory
 */

$currentUser = new \Yiisoft\User\CurrentUser($identityRepository, $eventDispatcher, $guestIdentityFactory);

此外,您还可以在运行时覆盖身份实例

/** 
 * @var \Yiisoft\Auth\IdentityInterface $identity
 */

$currentUser->getIdentity(); // Original identity instance
$currentUser->overrideIdentity($identity);
$currentUser->getIdentity(); // Override identity instance
$currentUser->clearIdentityOverride();
$currentUser->getIdentity(); // Original identity instance

这可以允许管理员或开发人员验证其他用户的问题。

登录和登出

有两种登录和登出方法

/**
 * @var \Yiisoft\Auth\IdentityInterface $identity
 */

$currentUser->getIdentity(); // GuestIdentityInterface instance

if ($currentUser->login($identity)) {
    $currentUser->getIdentity(); // $identity
    // Some actions
}

if ($currentUser->logout()) {
    $currentUser->getIdentity(); // GuestIdentityInterface instance
    // Some actions
}

两种方法都会触发事件。事件如下

  • Yiisoft\User\Event\BeforeLogin - 在登录过程开始时触发。此事件的监听器可以调用 $event->invalidate() 来取消登录过程。
  • Yiisoft\User\Event\AfterLogin - 在登录过程结束时触发。
  • Yiisoft\User\Event\BeforeLogout - 在登出过程开始时触发。此事件的监听器可以调用 $event->invalidate() 来取消登出过程。
  • Yiisoft\User\Event\AfterLogout - 在登出过程结束时触发。

这些事件的监听器可以使用 $event->getIdentity() 获取参与过程的身份实例。事件由指定的 Psr\EventDispatcher\EventDispatcherInterface 实例分发,该实例在初始化 Yiisoft\User\CurrentUser 实例时在构造函数中指定。

检查用户访问权限

要检查当前用户是否可以执行与给定权限相对应的操作,您需要设置访问检查器(请参阅 yiisoft/access)实例

/** 
 * @var \Yiisoft\Access\AccessCheckerInterface $accessChecker
 */
 
$currentUser = $currentUser->withAccessChecker($accessChecker);

要执行检查,请使用 can() 方法

// The name of the permission (e.g. "edit post") that needs access check.
$permissionName = 'edit-post'; // Required.

// Name-value pairs that would be passed to the rules associated with the roles and permissions assigned to the user.
$params = ['postId' => 42]; // Optional. Default is empty array.

if ($currentUser->can($permissionName, $params)) {
    // Some actions
}

请注意,如果没有通过 withAccessChecker() 方法提供访问检查器,则 can() 将始终返回 false

会话使用

当前用户可以将用户 ID 和身份验证超时存储在会话中,以进行自动登录。为此,您需要提供会话(请参阅 yiisoft/session)实例

/** 
 * @var \Yiisoft\Session\SessionInterface $session
 */
 
$currentUser = $currentUser->withSession($session);

您可以设置超时(秒数),在此期间用户在保持活动状态时将被自动登出

$currentUser = $currentUser->withAuthTimeout(3600);

此外,还可以使用绝对超时(秒数)。无论活动与否,用户都会被自动登出

$currentUser = $currentUser->withAbsoluteAuthTimeout(3600);

默认情况下,不使用超时,因此用户在当前会话过期后将被注销。

与事件循环一起使用

Yiisoft\User\CurrentUser 实例是有状态的,所以当您使用 Swoole 或 RoadRunner 等工具构建长时间运行的应用程序时,您应该在每次请求时重置状态。为此,您可以使用 clear() 方法。

通过请求属性中的身份自动登录

对于自动登录,您可以使用 Yiisoft\User\Login\LoginMiddleware。此中间件如果请求属性中存在 Yiisoft\Auth\IdentityInterface 实例,将自动登录用户。它通常由 Yiisoft\Auth\Middleware\Authentication 放在那里。有关认证中间件和认证方法的更多信息,请参阅 yiisoft/auth

请注意,Yiisoft\Auth\Middleware\Authentication 应位于中间件堆栈中的 Yiisoft\User\Login\LoginMiddleware 之前。

通过 cookie 自动登录

要基于请求 cookie 的存在自动登录用户,请使用 Yiisoft\User\Login\Cookie\CookieLoginMiddleware

要使用中间件,您需要实现 Yiisoft\User\Login\Cookie\CookieLoginIdentityInterface,并在 CurrentUser 中实现和使用一个 IdentityRepositoryInterface 实例,该实例将返回 CookieLoginIdentityInterface

use App\CookieLoginIdentity;
use Yiisoft\Auth\IdentityRepositoryInterface;

final class CookieLoginIdentityRepository implements IdentityRepositoryInterface
{
    private Storage $storage;

    public function __construct(Storage $storage)
    {
        $this->storage = $storage;
    }

    public function findIdentity(string $id): ?Identity
    {   
        return new CookieLoginIdentity($this->storage->findOne($id));
    }
}

CookieLoginMiddleware 将检查请求中是否存在 cookie,验证它并自动登录用户。

创建 cookie

默认情况下,您应该在用户登录后手动在您的应用程序中设置自动登录的 cookie

public function login(
    \Psr\Http\Message\ServerRequestInterface $request,
    \Psr\Http\Message\ResponseFactoryInterface $responseFactory,
    \Yiisoft\User\Login\Cookie\CookieLogin $cookieLogin,
    \Yiisoft\User\CurrentUser $currentUser
): \Psr\Http\Message\ResponseInterface {
    $response = $responseFactory->createResponse();
    $body = $request->getParsedBody();
    
    // Get user identity based on body content.
    
    /** @var \Yiisoft\User\Login\Cookie\CookieLoginIdentityInterface $identity */
    
    if ($currentUser->login($identity) && ($body['rememberMe'] ?? false)) {
        $response = $cookieLogin->addCookie($identity, $response);
    }
    
    return $response;
}

在上面的请求体中的 rememberMe 可能来自表单中的“记住我”复选框。最终用户决定是否希望自动登录。如果您不需要用户能够选择并且希望始终使用“记住我”,您可以通过 params.php 中的 forceAddCookie 启用它

return [
    'yiisoft/user' => [
        'authUrl' => '/login',
        'cookieLogin' => [
            'forceAddCookie' => true,
            'duration' => 'P5D', // 5 days
        ],
    ],
];

如果您希望 cookie 是会话 cookie,请将持续时间更改为 null

删除 cookie

Yiisoft\User\Login\Cookie\CookieLoginMiddleware 在注销后自动删除 cookie。但您也可以手动删除 cookie

public function logout(
    \Psr\Http\Message\ResponseFactoryInterface $responseFactory,
    \Yiisoft\User\Login\Cookie\CookieLogin $cookieLogin,
    \Yiisoft\User\CurrentUser $currentUser
): \Psr\Http\Message\ResponseInterface {
    $response = $responseFactory
        ->createResponse(302)
        ->withHeader('Location', '/');
    
    // Regenerate cookie login key to `Yiisoft\User\Login\Cookie\CookieLoginIdentityInterface` instance.
    
    if ($currentUser->logout()) {
        $response = $cookieLogin->expireCookie($response);
    }
    
    return $response;
}

防止 cookie 替换

登录 cookie 值以原始形式存储。为了防止 cookie 值的替换,您可以使用 Yiisoft\Cookies\CookieMiddleware。更多信息请参阅 Yii 关于 cookie 的指南

请注意,Yiisoft\Cookies\CookieMiddleware 应位于中间件堆栈中的 Yiisoft\User\Login\Cookie\CookieLoginMiddleware 之前。

您可以在 yiisoft/demo 中找到上述功能的示例。

文档

如果您需要帮助或有问题,Yii 论坛 是一个好地方。您还可以查看其他 Yii 社区资源

许可

Yii 用户是免费软件。它根据 BSD 许可证发布。有关更多信息,请参阅 LICENSE

Yii 软件 维护。

支持项目

Open Collective

关注更新

Official website Twitter Telegram Facebook Slack