pauldevelop/library-auth

常用类,用于验证用户和资源的身份验证和授权。

0.0.2 2017-07-20 19:44 UTC

This package is not auto-updated.

Last update: 2024-09-28 16:25:58 UTC


README

此库允许您的应用程序检查用户是否具有特定角色以及该用户是否被允许访问应用程序的某些部分。目前它假定,您的用户对象可以通过整数id访问,而角色对象可以通过包含角色名称的字符串访问。

用法

首先创建一个新的Authorisator对象;构造函数需要一个实现IRoleChecker接口的对象和一个变量集合。

$variables = new VariableCollection();
$variables->add(new Variable('baseHost', 'example.com'));

$authorisator = new Authorisator(
    new MyRoleChecker(), // implements IRoleChecker
    $variables
);

IRoleChecker接口定义了一个check方法,该方法接受用户ID和角色名称作为参数;实现必须检查ID为$id的用户是否具有名称为$roleName的角色。您不需要直接调用IRoleChecker,它将由Authorisator的check方法调用。

一个示例IRoleChecker实现可能如下所示

class MyRoleChecker implements IRoleChecker
{
    /**
     * @var model\ImpersonationPeer
     */
    private $impersonationPeer;

    /**
     * @var model\RolePeer
     */
    private $rolePeer;

    public function __construct(model\ImpersonationPeer $impersonationPeer = null, model\RolePeer $rolePeer = null)
    {
        $this->impersonationPeer = $impersonationPeer;
        $this->rolePeer = $rolePeer;
    }

    public function check($id = 0, $roleName = '')
    {
        // init
        $result = false;

        // action
        $roles = $this->rolePeer->queryPath('role[@name='.$roleName.']#');
        if (count($roles) == 1) {
            /** @var model\Role $role */
            $role = $roles[0];
            $impersonations = $this->impersonationPeer->queryPath(
                'impersonation[@user='.$id.',@role='.$role->Id.']#'
            );
            if (count($impersonations) == 1) {
                $result = true;
            }
        }

        // return
        return $result;
    }
}

在这个例子中,构造函数接受两个对等对象,它们从数据库等数据源访问数据。角色由RolePeer读取,而用户假冒哪个角色的信息通过ImpersonationPeer读取。首先,我们查询具有$roleName的角色;如果我们找到了一个角色,我们也检查用户$id是否假冒了角色$roleName。如果是,我们返回true,否则返回false。

在实例化Authorisator对象时记录的变量集合包含可以在下一节描述的模式中使用的变量。

下一步是添加访问限制,这通过在Authorisator对象上调用addAccessRestriction方法来完成。此方法接受一个具有以下属性的AccessRestriction对象作为参数

  • pattern

    描述资源URL的模式。在这个例子中,我们定义了一个变量baseHost,我们可以通过将名称用%符号包围来使用它(%baseUrl%)。如果您在末尾添加通配符(*),则也会保护以给定路径开始的任何URL。

  • authenticator

    一个用于验证用户的认证器。

  • roleName

    用户必须具有的角色名称。

  • callbackUrl

    如果用户不允许访问资源,则调用的URL。

  • callback

    当callbackUrl为空且用户不允许访问资源时调用的函数。

  • exceptionPaths

    一个资源URL模式数组,这些模式必须不进行检查,因此例如对于登录表单的URL非常有用。您可以使用%baseHost%变量。

要仅允许具有“管理员”角色的用户访问后端资源,请按以下方式调用addAccessRestriction方法

$authorisator->addAccessRestriction(
    new AccessRestriction(
        'backend.%baseHost%/*',
        new CredentialAuthenticator(), // implements IAuthenticator
        'Administrator',
        'http://backend.%baseHost%/login/',
        null,
        array(
            'backend.%baseHost%/login/',
            'backend.%baseHost%/login/process/'
        )
    )
);

IAuthenticator接口的一个示例实现可能如下所示

class CredentialAuthenticator implements IAuthenticator
{
    /**
     * @var IPathQueryable
     */
    private $storage;

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

    /**
     * @param Entity $credentialEntity
     *
     * @return bool
     */
    public function check(Entity $credentialEntity)
    {
        // init
        $result = false;

        // action
        if (($nameProperty = $credentialEntity->Properties['name']) !== null) {
            /** @var IPathQueryable $storage */
            $storage = $this->storage;
            $userList = $storage->queryPath('user[@name='.$nameProperty->Value.']#');
            if ( sizeof($userList) > 0 ) {
                /** @var Entity $userEntity */
                $userEntity = $userList[0];
                if ($userEntity != null
                    && password_verify(
                        $credentialEntity->Properties['password']->Value,
                        $storageEntity->Properties['password']->Value
                    )
                ) {
                    $result = $storageEntity->Properties['id']->Value;
                }
            }
        }

        // return
        return $result;
    }
}

在这个例子中,check方法接收形式为名称和密码的凭据。如果设置名称属性,我们将查询存储,以确定是否知道具有该名称的用户。然后我们验证密码并返回用户的ID。您可以轻松修改此类以检查用户IP或会话ID。

现在是我们实际检查资源是否对用户可访问的时候了。使用 Authorisator 对象的 check 方法来完成这个操作。

// setup credentials
$credentials = new Entity();
$credentials->Properties = new IPropertyCollection();
$result->Properties->add(new Property('name', $name), 'name');
$result->Properties->add(new Property('password', $password), 'password');

if ($authorisator->check($url, $credentials)) {
  // load protected content
}