aura/auth

提供统一的接口,用于使用本地或远程身份验证系统对用户进行身份验证。

4.0.3 2021-12-15 20:58 UTC

This package is auto-updated.

Last update: 2024-09-08 15:06:06 UTC


README

提供使用各种适配器实现的身份验证功能和会话跟踪;当前支持的适配器包括

  • Apache htpasswd 文件
  • 通过 PDO 扩展的 SQL 表
  • 通过 imap 扩展的 IMAP/POP/NNTP
  • 通过 ldap 扩展的 LDAP 和 Active Directory
  • 通过自定义适配器的 OAuth

请注意,此包的目的仅用于验证用户凭据。目前它不会处理用户账户的创建和管理,未来可能也不会。这更适合应用层功能,或者至少是一个独立的 Aura 包。

前言

安装

此库需要 PHP 7.2 或更高版本,没有用户空间依赖。

可以通过 Composer 作为 aura/auth 安装和自动加载。

或者,下载一个版本 或克隆此存储库,然后要求或包含其 autoload.php 文件。

质量

Scrutinizer Code Quality Code Coverage Build Status

要在命令行运行单元测试,请先执行 composer install,然后在包根目录中执行 vendor/bin/phpunit。这需要 Composer 作为 composer 可用。

此库尝试遵守 PSR-1PSR-2PSR-4。如果您注意到合规性疏忽,请通过拉取请求发送补丁。

社区

要提问、提供反馈或与其他 Aura 社区进行交流,请加入我们的 Google Group,关注 @auraphp 或在 Freenode 上与我们聊天。

入门

实例化

要跟踪身份验证状态和相关信息,请使用 AuthFactory 创建一个 Auth 对象。

<?php
$auth_factory = new \Aura\Auth\AuthFactory($_COOKIE);
$auth = $auth_factory->newInstance();
?>

您可以使用以下方法从 Auth 实例检索身份验证信息

  • getUserName():返回已验证的用户名字符串

  • getUserData():返回包含可选任意用户数据的数组

  • getFirstActive():返回第一次活动(登录)的 Unix 时间

  • getLastActive():返回最近一次活动(通常是当前请求)的 Unix 时间

  • getStatus():返回当前身份验证状态的常量。这些常量是

    • Status::ANON -- 匿名/未认证

    • Status::IDLE -- 已认证会话空闲时间过长

    • Status::EXPIRED -- 已认证会话的总持续时间过长

    • Status::VALID -- 已认证且有效

  • isAnon()isIdle()isExpired()isValid():这些返回基于当前身份验证状态的 true 或 false。

您还可以使用上面提到的 get*() 方法的 set*() 变体来强制 Auth 对象具有您喜欢的任何值。然而,因为这些值存储在 $_SESSION 段中,所以如果没有运行会话,这些值将不会保留。

要保留会话中的值,您可以通过在自己的代码中调用 session_start() 来强制启动会话。或者,使用 Aura.Auth 包的服务来处理身份验证和会话状态管理会更好。

服务

本包提供了三个服务来处理身份验证阶段

  • LoginService 用于登录和启动(或恢复)会话,

  • LogoutService 用于登出并从会话中删除用户名和用户数据(请注意,这 不会 销毁会话),以及

  • ResumeService 用于恢复之前启动的会话。

您可以使用 AuthFactory 创建每个服务。现在,我们将看看如何强制登录和登出;稍后,我们将展示如何让服务使用凭证适配器。

强制登录

您可以通过使用用户名和可选的任意用户数据调用 LoginServiceforceLogin() 方法来强制将 Auth 对象置于登录状态。

<?php
// the authentication status is currently anonymous
echo $auth->getStatus(); // ANON

// create the login service
$login_service = $auth_factory->newLoginService();

// use the service to force $auth to a logged-in state
$username = 'boshag';
$userdata = array(
    'first_name' => 'Bolivar',
    'last_name' => 'Shagnasty',
    'email' => 'boshag@example.com',
);
$login_service->forceLogin($auth, $username, $userdata);

// now the authentication status is valid
echo $auth->getStatus(); // VALID
?>

使用 forceLogin() 有以下副作用

  • 如果没有已经启动会话,则启动一个新的会话,如果存在则恢复之前的会话

  • 重新生成会话 ID

指定的用户名和用户数据将存储在 $_SESSION 段中,并附带 Status::VALID 的身份验证状态。

请注意,forceLogin() 不会检查任何凭证来源。作为应用程序的所有者,您正在强制将 Auth 对象置于登录状态。

强制登出

您可以通过调用 LogoutServiceforceLogout() 方法来强制将 Auth 对象置于登出状态。

<?php
// the authentication status is currently valid
echo $auth->getStatus(); // VALID

// create the logout service
$logout_service = $auth_factory->newLogoutService();

// use the service to force $auth to a logged-out state
$logout_service->forceLogout($auth);

// now the authentication status is anonymous/invalid
echo $auth->getStatus(); // ANON
?>

使用 forceLogout() 有以下副作用

  • $_SESSION 段中清除任何现有的用户名和用户数据

  • 重新生成会话 ID

请注意,forceLogout() 不会检查任何凭证来源。作为应用程序的所有者,您正在强制将 Auth 对象置于登出状态。

请注意,这也 不会 销毁会话。这是因为您可能需要在会话内存中保留其他东西,例如闪存消息。

恢复会话

当 PHP 请求结束时,PHP 会为您保存 $_SESSION 数据。然而,在下一个请求中,PHP 不会自动为您启动一个新的会话,因此 $_SESSION 不会自动可用。

您可以自己启动一个新的会话来重新填充 $_SESSION,但这会带来性能开销,如果您实际上不需要会话数据。同样,在之前没有会话(因此没有数据要重新填充到 $_SESSION)的情况下,可能没有必要启动会话。我们需要的是一种方法,在之前已启动会话时启动会话,但在没有启动会话时避免启动会话。

存在 ResumeService 来解决这个问题。当您在 ResumeService 上调用 resume() 方法时,它会检查 $_COOKIE 以查看是否存在会话cookie

  • 如果不存在cookie,它将不会启动会话,并返回到调用代码。这避免了在没有 $_SESSION 数据要填充的情况下启动会话。

  • 如果存在cookie,ResumeService 将启动会话,从而重新填充 $_SESSION。然后,它将根据会话存在的时间更新身份验证状态

    • 如果会话空闲时间过长(即,自上次请求以来已过去很长时间),ResumeService 将自动将用户登出并返回到调用代码。

    • 如果会话已过期(即,总登录时间过长),ResumeService 也将自动将用户登出并返回到调用代码。

    • 否则,ResumeService 将更新 Auth 对象的最近活跃时间,并返回到调用代码。

通常,您希望在应用程序周期的开始处调用 ResumeService,以便在最早的机会使会话数据可用。

<?php
// create the resume service
$resume_service = $auth_factory->newResumeService();

// use the service to resume any previously-existing session
$resume_service->resume($auth);

// $_SESSION has now been repopulated, if a session was started previously,
// meaning the $auth object is now populated with its previous values, if any
?>

适配器

强制将 Auth 对象设置为特定状态,当您想要手动控制身份验证状态、用户名、用户数据和其他信息时是可行的。然而,更常见的情况是您想要将用户凭证输入(用户名和密码)与凭证存储进行比对。这就是 Adapter 类发挥作用的地方。

要使用 AdapterService,您首先需要创建 Adapter,然后将它传递给 AuthFactorynew*Service() 方法。

Htpasswd 适配器

实例化

要创建 Apache htpasswd 文件的适配器,调用 AuthFactorynewHtpasswdAdapter() 方法,并传递 Apache htpasswd 文件的路径。

<?php
$htpasswd_adapter = $auth_factory->newHtpasswdAdapter(
    '/path/to/accounts.htpasswd'
);
?>

这将自动使用 HtpasswdVerifier 来检查来自 htpasswd 文件的每个用户的 DES、MD5 和 SHA 密码。

服务集成

然后,您可以像这样将 Adapter 传递给每个 Service 工厂方法

<?php
$login_service = $auth_factory->newLoginService($htpasswd_adapter);
$logout_service = $auth_factory->newLogoutService($htpasswd_adapter);
$resume_service = $auth_factory->newResumeService($htpasswd_adapter);
?>

要尝试用户登录,将包含 usernamepassword 元素的数组传递给 LoginServicelogin() 方法,并附带 Auth 对象

<?php
$login_service->login($auth, array(
    'username' => 'boshag',
    'password' => '12345'
));
?>

有关 LoginService 习惯用法的更多信息,请参阅服务习惯用法部分。(LogoutServiceResumeService 不需要凭证信息。)

IMAP/POP/NNTP 适配器

实例化

要创建 IMAP/POP/NNTP 服务器的适配器,调用 AuthFactorynewImapAdapter() 方法,并传递邮箱规范字符串,以及任何适当的选项常量

<?php
$imap_adapter = $auth_factory->newImapAdapter(
    '{mail.example.com:143/imap/secure}',
    OP_HALFOPEN
);
?>

注意:有关邮箱规范字符串的更多变体,请参阅 imap_open() 文档。

服务集成

然后,您可以像这样将 Adapter 传递给每个 Service 工厂方法

<?php
$login_service = $auth_factory->newLoginService($imap_adapter);
$logout_service = $auth_factory->newLogoutService($imap_adapter);
$resume_service = $auth_factory->newResumeService($imap_adapter);
?>

要尝试用户登录,将包含 usernamepassword 元素的数组传递给 LoginServicelogin() 方法,并附带 Auth 对象

<?php
$login_service->login($auth, array(
    'username' => 'boshag',
    'password' => '12345'
));
?>

有关 LoginService 习惯用法的更多信息,请参阅服务习惯用法部分。(LogoutServiceResumeService 不需要凭证信息。)

LDAP 适配器

实例化

要创建 LDAP 和 Active Directory 服务器的适配器,调用 AuthFactorynewLdapAdapter() 方法,并传递包含唯一名称(DN)格式的字符串的服务器名称

<?php
$ldap_adapter = $auth_factory->newLdapAdapter(
    'ldaps://ldap.example.com:636',
    'ou=Company Name,dc=Department Name,cn=users,uid=%s'
);
?>

注意:用户名将通过 sprintf() 进行转义,然后传递给 DN 格式字符串。完成后的 DN 将在连接后用于绑定到服务器。

服务集成

然后,您可以像这样将 Adapter 传递给每个 Service 工厂方法

<?php
$login_service = $auth_factory->newLoginService($ldap_adapter);
$logout_service = $auth_factory->newLogoutService($ldap_adapter);
$resume_service = $auth_factory->newResumeService($ldap_adapter);
?>

要尝试用户登录,将包含 usernamepassword 元素的数组传递给 LoginServicelogin() 方法,并附带 Auth 对象

<?php
$login_service->login($auth, array(
    'username' => 'boshag',
    'password' => '12345'
));
?>

有关 LoginService 习惯用法的更多信息,请参阅服务习惯用法部分。(LogoutServiceResumeService 不需要凭证信息。)

PDO 适配器

实例化

要创建与 SQL 表的 PDO 连接的适配器,调用 AuthFactorynewPdoAdapter() 方法,并按顺序传递以下参数

  • 一个 PDO 连接实例

  • 表示数据库中密码哈希方式的指示

    • 如果是一个来自 PHP 5.5 及以上版本的 PASSWORD_* 常量,它被视为用于 PasswordVerifier 实例的 password_hash() 算法(这是首选方法)

    • 如果是一个字符串,它被视为用于 HashVerifier 实例的 hash() 算法

    • 否则,它预期是一个 VerifierInterface 的实现

  • 列名数组:第一个元素是用户名列,第二个元素是哈希密码列,额外的列用于从数据库中选择和返回额外的用户信息

  • 一个 FROM 规范字符串,用于指示一个或多个表名,以及您希望添加的任何其他 JOIN 子句

  • 一个可选的 WHERE 条件字符串;使用此字符串添加到适配器构建的 SELECT 语句中的额外条件

这是一个使用 MD5 哈希在帐户表中密码的遗留示例

<?php
$pdo = new \PDO(...);
$hash = new PasswordVerifier('md5');
$cols = array('username', 'md5password');
$from = 'accounts';
$pdo_adapter = $auth_factory->newPdoAdapter($pdo, $hash, $cols, $from);
?>

这是一个使用 bcrypt 替代 md5、从连接的表检索额外的用户信息列并筛选活动帐户的现代、更复杂的示例

<?php
$pdo = new \PDO(...);
$hash = new PasswordVerifier(PASSWORD_BCRYPT);
$cols = array(
    'accounts.username', // "AS username" is added by the adapter
    'accounts.bcryptpass', // "AS password" is added by the adapter
    'accounts.uid AS uid',
    'userinfo.email AS email',
    'userinfo.uri AS website',
    'userinfo.fullname AS display_name',
);
$from = 'accounts JOIN profiles ON accounts.uid = profiles.uid';
$where = 'accounts.active = 1';
$pdo_adapter = $auth_factory->newPdoAdapter($pdo, $hash, $cols, $from, $where);
?>

(在成功认证后,额外的信息列将保留在会话数据中。)

服务集成

然后,您可以像这样将 Adapter 传递给每个 Service 工厂方法

<?php
$login_service = $auth_factory->newLoginService($pdo_adapter);
$logout_service = $auth_factory->newLogoutService($pdo_adapter);
$resume_service = $auth_factory->newResumeService($pdo_adapter);
?>

要尝试用户登录,将包含 usernamepassword 元素的数组传递给 LoginServicelogin() 方法,并附带 Auth 对象

<?php
$login_service->login($auth, array(
    'username' => 'boshag',
    'password' => '12345'
));
?>

有关 LoginService 习惯用法的更多信息,请参阅服务习惯用法部分。(LogoutServiceResumeService 不需要凭证信息。)

自定义适配器

尽管这个包包含多个适配器类,但可能没有一个符合您的需求。

您可能希望扩展现有的适配器以添加登录/注销/恢复行为。或者,您可以通过在所选类上实现适配器接口来创建自己的适配器

<?php
use Aura\Auth\Adapter\AdapterInterface;
use Aura\Auth\Auth;
use Aura\Auth\Status;

class CustomAdapter implements AdapterInterface
{
    // AdapterInterface::login()
    public function login(array $input)
    {
        if ($this->isLegit($input)) {
            $username = ...;
            $userdata = array(...);
            $this->updateLoginTime(time());
            return array($username, $userdata);
        } else {
            throw CustomException('Something went wrong.');
        }
    }

    // AdapterInterface::logout()
    public function logout(Auth $auth, $status = Status::ANON)
    {
        $this->updateLogoutTime($auth->getUsername(), time());
    }

    // AdapterInterface::resume()
    public function resume(Auth $auth)
    {
        $this->updateActiveTime($auth->getUsername(), time());
    }

    // custom support methods not in the interface
    protected function isLegit($input) { ... }

    protected function updateLoginTime($time) { ... }

    protected function updateActiveTime($time) { ... }

    protected function updateLogoutTime($time) { ... }
}
?>

然后您可以通过AuthFactory方法创建服务时传递自定义适配器的实例

<?php
$custom_adapter = new CustomAdapter;
$login_service = $auth_factory->newLoginService($custom_adapter);
$logout_service = $auth_factory->newLogoutService($custom_adapter);
$resume_service = $auth_factory->newResumeService($custom_adapter);
?>
OAuth适配器

如果您希望通过使用OAuth 2.0的第三方服务来处理身份验证,则需要编写一个实现Aura\Auth\Adapter\AdapterInterface的适配器,并提供您自己的获取访问令牌和用户信息的实现。您的实现可以是您自己编写的,也可以是现有的OAuth2客户端。

以下示例将展示如何使用PHP League的OAuth2客户端创建此适配器。在这个例子中,我们将使用GitHub作为服务提供商。

<?php
namespace OAuth2\Adapter;

use Aura\Auth\Adapter\AdapterInterface;
use Aura\Auth\Exception;
use Aura\Auth\Auth;
use Aura\Auth\Status;
use League\OAuth2\Client\Provider\AbstractProvider;

class LeagueOAuth2Adapter implements AdapterInterface
{

    /**
     * @var \League\OAuth2\Client\Provider\IdentityProvider
     * The identity provider that the adapter will use
     */
    protected $provider;

    public function __construct(AbstractProvider $provider)
    {
        $this->provider = $provider;
    }

    /**
     * @param $input an input containing the OAuth 2 code
     * @return array the username and details for the user
     * @throws \Aura\Auth\Exception
     * This method must be implemented to fulfill the contract
     * with AdapterInterface
     */
    public function login(array $input)
    {
        if (!isset($input['code'])) {
            throw new Exception('Authorization code missing.');
        }

        $token = $this->provider->getAccessToken(
            'authorization_code',
            array('code' => $input['code'])
        );

        $details = $this->provider->getResourceOwner($token);
        $data = [
            'name' => $details->getName(),
            'email' => $details->getEmail(),
        ];
        $data['token'] = $token;
        $username = $data['email'];
        return [$username, $data];
    }

    /**
     * @param Auth $auth
     * Logout method is required to fulfill the contract with AdapterInterface
     */
    public function logout(Auth $auth, $status = Status::ANON)
    {
        //nothing to do here
    }

    /**
     * @param Auth $auth
     * Resume method required to fulfill the contract with AdapterInterface
     */
    public function resume(Auth $auth)
    {
        // nothing to do here
    }
}
?>

如代码所示,您的适配器将接受一个客户端作为参数,并使用该客户端来履行\Aura\Auth\Adapter\AdapterInterface协议。此适配器通常用于OAuth2回调过程。本质上,一旦您提供了凭证并与第三方服务(在本例中为GitHub)进行身份验证,您将被重定向回您服务器上的一个脚本,在那里您需要通过将验证码发送回服务来验证您发送了请求。这就是为什么使用好的OAuth2客户端而不是编写自己的代码是一个好主意。以下是OAuth2回调代码的示例。

<?php
namespace OAuth2;

use Aura\Auth\AuthFactory;
use League\OAuth2\Client\Provider\Github;
use OAuth2\Adapter\LeagueOAuth2Adapter;
use Aura\Auth\Exception;

require_once 'vendor/autoload.php';

$auth_factory = new AuthFactory($_COOKIE);
$auth = $auth_factory->newInstance();

$github_provider = new Github(array(
    'clientId' => 'xxxxxxxxxxxxxxxx',
    'clientSecret' => 'xxxxxxxxxxxxxxxxxxxx',
    'redirectUri' => 'http://aura.auth.dev/'
));

if (!isset($_GET['code'])) {
    header('Location: ' . $github_provider->getAuthorizationUrl());
    exit;
} else {
    $oauth_adapter = new LeagueOAuth2Adapter($github_provider);
    $login_service = $auth_factory->newLoginService($oauth_adapter);
    try {
        // array is the username and an array of info and indicates successful
        // login
        $data = $login_service->login($auth, $_GET);
    } catch (Exception $e) {
        // handle the exception
    }
}
?>

由于并非每个第三方服务都以相同的方式返回数据,因此Aura尝试处理每种不同的数据集是不合理的。通过编写这段代码,您可以轻松地将Aura Auth应用于您的第三方OAuth2服务。

服务惯用语

恢复会话

以下是恢复现有会话所需的代码示例。请注意,echo语句的目的是解释resume()调用的不同结果状态,可以根据您认为合适的逻辑进行替换。例如,您可能希望在会话空闲或过期时重定向到登录页面。

<?php
$auth = $auth_factory->newInstance();

$resume_service = $auth_factory->newResumeService(...);
$resume_service->resume($auth);

switch (true) {
    case $auth->isAnon():
        echo "You are not logged in.";
        break;
    case $auth->isIdle():
        echo "Your session was idle for too long. Please log in again.";
        break;
    case $auth->isExpired():
        echo "Your session has expired. Please log in again.";
        break;
    case $auth->isValid():
        echo "You are still logged in.";
        break;
    default:
        echo "You have an unknown status.";
        break;
}
?>

注意:您可能希望使用依赖注入容器(例如Aura.Di)手动创建AuthResumeService对象,以在您的应用程序中保留它们供共享使用。

登录

以下是实现登录所需的代码示例。请注意,echo$log语句的目的是解释login()调用的不同结果状态,可以根据您认为合适的逻辑进行替换;特别是,您可能不希望暴露失败的精确性质,以帮助减轻暴力尝试。

<?php

class InvalidLoginException extends Exception {}

$auth = $auth_factory->newInstance();

$login_service = $auth_factory->newLoginService(...);

try {

    $login_service->login($auth, array(
        'username' => $_POST['username'],
        'password' => $_POST['password'],
    );
    echo "You are now logged into a new session.";

} catch (\Aura\Auth\Exception\UsernameMissing $e) {

    $log->notice("The 'username' field is missing or empty.");
    throw new InvalidLoginException();

} catch (\Aura\Auth\Exception\PasswordMissing $e) {

    $log->notice("The 'password' field is missing or empty.");
    throw new InvalidLoginException();

} catch (\Aura\Auth\Exception\UsernameNotFound $e) {

    $log->warning("The username you entered was not found.");
    throw new InvalidLoginException();

} catch (\Aura\Auth\Exception\MultipleMatches $e) {

    $log->warning("There is more than one account with that username.");
    throw new InvalidLoginException();

} catch (\Aura\Auth\Exception\PasswordIncorrect $e) {

    $log->notice("The password you entered was incorrect.");
    throw new InvalidLoginException();

} catch (\Aura\Auth\Exception\ConnectionFailed $e) {

    $log->notice("Cound not connect to IMAP or LDAP server.");
    $log->info("This could be because the username or password was wrong,");
    $log->info("or because the the connect operation itself failed in some way. ");
    $log->info($e->getMessage());
    throw new InvalidLoginException();

} catch (\Aura\Auth\Exception\BindFailed $e) {

    $log->notice("Cound not bind to LDAP server.");
    $log->info("This could be because the username or password was wrong,");
    $log->info("or because the the bind operation itself failed in some way. ");
    $log->info($e->getMessage());
    throw new InvalidLoginException();

} catch (InvalidLoginException $e) {

    echo "Invalid login details. Please try again.";

}
?>

注意:您可能希望使用依赖注入容器(例如Aura.Di)手动创建AuthLoginService对象,以在您的应用程序中保留它们供共享使用。

或者,您可能希望使用HTTP Authorization: Basic头部的凭据而不是使用$_POST或其他与表单相关的输入。在Apache mod_php上,您可能使用自动填充的$_SERVER['PHP_AUTH_*']

<?php
$authorization_basic = function () {
    return array(
        isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null,
        isset($_SERVER['PHP_AUTH_PW'])   ? $_SERVER['PHP_AUTH_PW']   : null,
    );
}

list($username, $password) = $authorization_basic();
$login_service->login($auth, array(
    'username' => $username,
    'password' => $password,
));
?>

在其他服务器上,您可能需要从Authorization: Basic头部本身提取凭据

<?php
$authorization_basic = function () {

    $header = isset($_SERVER['HTTP_AUTHORIZATION'])
            ? $_SERVER['HTTP_AUTHORIZATION']
            : '';

    if (strtolower(substr($header, 0, 6)) !== 'basic ') {
        return array(null, null);
    }

    $encoded = substr($header, 6);
    $decoded = base64_decode($encoded);
    return explode(':', $decoded);

}

list($username, $password) = $authorization_basic();
$login_service->login($auth, array(
    'username' => $username,
    'password' => $password,
));
?>

注销

这是实现注销所需的代码示例。请注意,echo语句旨在解释logout()调用的不同结果状态,可以根据需要替换为任何逻辑。

<?php
$auth = $auth_factory->newInstance();

$logout_service = $auth_factory->newLogoutService(...);

$logout_service->logout($auth);

if ($auth->isAnon()) {
    echo "You are now logged out.";
} else {
    echo "Something went wrong; you are still logged in.";
}
?>

注意:您可以使用依赖注入容器(例如Aura.Di)而不是手动创建AuthLogoutService对象,以在整个应用程序中保持它们以供共享使用。

自定义服务

您不受此包提供的登录、注销和恢复服务的限制。但是,如果您构建了自己的服务或扩展了提供的某个服务,您将不得不手动实例化该自定义服务对象,而不是使用AuthFactory。这可能会很繁琐,但并不困难,尤其是在使用Aura.Di等依赖注入容器系统时。

会话管理

Service对象使用Session对象来启动会话并重新生成会话ID。(注意,它们不会销毁会话。)Session对象使用原生PHP的session_*()函数来管理会话。

自定义会话

如果您希望使用其他方式来管理会话,可以在您选择的对象上实现SessionInterface。一种方法是包装框架特定的会话对象,并将SessionInterface方法代理到包装对象。

<?php
use Aura\Auth\Session\SessionInterface;

class CustomSession implements SessionInterface
{
    protected $fwsession;

    public function __construct(FrameworkSession $fwsession)
    {
        $this->fwsession = $fwsession;
    }

    public function start()
    {
        return $this->fwsession->startSession();
    }

    public function resume()
    {
        if ($this->fwsession->isAlreadyStarted()) {
            return true;
        }

        if ($this->fwsession->canBeRestarted()) {
            return $this->fwsession->restartSession();
        }

        return false;
    }

    public function regenerateId()
    {
        return $this->fwsession->regenerateSessionId();
    }
}
?>

然后,将自定义会话对象传递给AuthFactory实例化。

<?php
use Aura\Auth\AuthFactory;

$custom_session = new CustomSession(new FrameworkSession);
$auth_factory = new AuthFactory($_COOKIE, $custom_session);
?>

工厂将把您的自定义会话对象传递到需要的地方。

不使用会话进行工作

在某些情况下,例如与API一起使用,其中每个请求都提供了凭据,避免使用会话可能会有所帮助。在这种情况下,将NullSessionNullSegment传递给AuthFactory

<?php
use Aura\Auth\AuthFactory;
use Aura\Auth\Session\NullSession;
use Aura\Auth\Session\NullSegment;

$null_session = new NullSession;
$null_segment = new NullSegment;
$auth_factory = new AuthFactory($_COOKIE, $null_session, $null_segment);
?>

对于NullSession,永远不会启动会话,也不会创建或重新生成会话ID。同样,由于在先前的请求结束时从未保存,永远不会恢复会话。最后,PHP永远不会创建会话cookie以发送到响应中。

同样,NullSegment将认证信息保留在对象属性中,而不是在$_SESSION段中。与仅在$_SESSION存在时保留数据的正常Segment不同,NullSegment将始终保留设置到其中的数据。当请求结束时,NullSegment中保留的所有信息都将消失。

使用NullSessionNullSegment时,您必须在每个请求上通过LoginServicelogin()forceLogin()方法检查凭据,这反过来会在Segment中保留认证信息。在API情况下,这通常比管理持续会话更可取。

注意:在API情况下,凭据可能是一个API令牌,或者作为HTTP基本或摘要认证头传递。将这些传递给您选择的适配器。

DI配置

以下是有关通过Aura.Di配置Aura.Auth的一些提示。

Aura\Auth\Adapter\HtpasswdAdapter

<?php
$di->params['Aura\Auth\Adapter\HtpasswdAdapter'] = array(
    'file' => '/path/to/htpasswdfile',
);
?>

Aura\Auth\Adapter\ImapAdapter

<?php
$di->params['Aura\Auth\Adapter\ImapAdapter'] = array(
    'mailbox' => '{mail.example.com:143/imap/secure}',
);
?>

Aura\Auth\Adapter\LdapAdapter

<?php
$di->params['Aura\Auth\Adapter\LdapAdapter'] = array(
    'server' => 'ldaps://ldap.example.com:636',
    'dnformat' => 'ou=Company Name,dc=Department Name,cn=users,uid=%s',
);
?>

Aura\Auth\Adapter\PdoAdapter

<?php
$di->params['Aura\Auth\Adapter\PdoAdapter'] = array(
    'pdo' => $di->lazyGet('your_pdo_connection_service'),
    'cols' => array(
        'username_column',
        'password_column',
    ),
    'from' => 'users_table',
    'where' => '',
);
?>