ZF2 - 假设其他用户的身份

ZF2 - Assuming other user's identity

在我开始重新发明轮子之前,我首先想检查 ZF2 是否支持,开箱即用或使用第 3 方库,管理员 log in as其他用户,或 assume 他们的身份。

如果不是,因为我不熟悉 ZF2 的内部设计,我将如何实现它,唯一的限制是系统已经构建,所以我不能更改组件(控制器,auth服务等)来支持它。

我的第一个想法是建立一种机制,将存储在会话存储中的已记录用户信息与我想采用其身份的用户进行切换。然后,在不同的命名空间下,将原始用户信息(admin)写入会话,以便可以将其还原。

通过这种方法,我期待像 Zend\Authentication\AuthenticationService return 我假设其身份的用户这样的组件。因此,在我对其他控制器中的 $this->identity()->getId()(身份是 AuthenticationService 的控制器插件,return 是 User)的每次调用中,业务逻辑将正常工作。

说到这里,问题就是:

  1. 是否已经有解决方案?
  2. 我的方法是否正确假设通过覆盖会话存储我可以假设其他用户 ID 并期望 ZF2 组件相应地工作,或者是否有关于 ZF2 内部的任何考虑 design/infrastructure 我没有考虑我应该考虑什么?
  3. 也许有更好的方法?

我认为您需要创建自己的 AuthenticationAdaptor。

class AdminUserLoginAsUser implements \Zend\Authentication\Adapter\AdapterInterface
{

    /**
     * @var User
     */
    private $userToLoginAs;

    /**
     * @var AdminUser
     */
    private $adminUser;

    public function __construct(User $userToLoginAs, AdminUser $adminUser)
    {

        $this->userToLoginAs = $userToLoginAs;
        $this->adminUser = $adminUser;
    }

    /**
     * Performs an authentication attempt
     *
     * @return \Zend\Authentication\Result
     * @throws \Zend\Authentication\Adapter\Exception\ExceptionInterface If authentication cannot be performed
     */
    public function authenticate()
    {
        return new \Zend\Authentication\Result(
            Result::SUCCESS, $this->user, [
                'You have assumed control of user.',
            ]
        );
    }
}

以上 class 将允许您在与 Zend 的 AuthenticationService class 一起使用时以另一个用户身份登录 class。

您将需要一些使用 Zend 的 AuthenticationService 的方法class,我建议使用 AuthManager 环绕 AuthenticationService。

/**
 * The AuthManager service is responsible for user's login/logout and simple access
 * filtering. The access filtering feature checks whether the current visitor
 * is allowed to see the given page or not.
 */
class AuthManager
{
    /**
     * Authentication service.
     * @var \Zend\Authentication\AuthenticationService
     */
    private $authService;

    /**
     * Session manager.
     * @var Zend\Session\SessionManager
     */
    private $sessionManager;

    /**
     * Contents of the 'access_filter' config key.
     * @var array
     */
    private $config;

    /**
     * Constructs the service.
     */
    public function __construct($authService, $sessionManager, $config)
    {
        $this->authService = $authService;
        $this->sessionManager = $sessionManager;
        $this->config = $config;
    }

    /**
     * Performs a login attempt. If $rememberMe argument is true, it forces the session
     * to last for one month (otherwise the session expires on one hour).
     */
    public function login($email, $password, $rememberMe)
    {
        // Check if user has already logged in. If so, do not allow to log in
        // twice.
        if ($this->authService->getIdentity()!=null) {
            throw new \Exception('Already logged in');
        }

        // Authenticate with login/password.
        $authAdapter = $this->authService->getAdapter();
        $authAdapter->setEmail($email);
        $authAdapter->setPassword($password);
        $result = $this->authService->authenticate();

        // If user wants to "remember him", we will make session to expire in
        // one month. By default session expires in 1 hour (as specified in our
        // config/global.php file).
        if ($result->getCode()==Result::SUCCESS && $rememberMe) {
            // Session cookie will expire in 1 month (30 days).
            $this->sessionManager->rememberMe(60*60*24*30);
        }

        return $result;
    }

    public function loginAsUser($user)
    {
        // Check if user has already logged in. If so, do not allow to log in
        // twice.
        if ($this->authService->getIdentity() !== null) {
            throw new \Exception('Not logged in.');
        }

        // First need to logout of current user
        $this->authService->clearIdentity();

        $authAdapter = $this->authService->setAdapter(new AdminUserLoginAsUser($user, $this->authService->getIdentity()));
        return $this->authService->authenticate();

    }

    /**
     * Performs user logout.
     */
    public function logout()
    {
        // Allow to log out only when user is logged in.
        if ($this->authService->getIdentity()==null) {
            throw new \Exception('The user is not logged in');
        }

        // Remove identity from session.
        $this->authService->clearIdentity();
    }

}

要了解如何将它们整合在一起,我建议您查看以下资源:

这些资源是针对 zf3 的,但我认为用户身份验证和管理身份验证与 zf2 非常相似。