第 3 章 Zend_Auth
上一页 |  | 下一页

## 第 3 章 Zend_Auth

## 3.1. 简介

Zend_Auth 为认证（authentication）提供了一个API并包括了一些通用用例情景的具体认证适配器。

| 注意
Zend_Auth 当前为设计包含了数字认证适配器作为一个简单的 proof-of-concept。其他的适配器正计划开发。对使用特定的适配器感兴趣？非常欢迎你的为适配器投票 和贡献！

Zend_Auth 只涉及 认证而不是授权。认证被宽松地定义为基于一些证书（credential）来确定一个实体（例如，身份）是否确实是它所声称的。授权是一个过程，它决定是否允许一个实体对其他实体进行访问、执行操作，它超出了Zend_Auth的范围。更多关于Zend Framework 授权和访问控制的信息，参见Zend_Acl.

### 3.1.1. 适配器

Zend_Auth适配器被用来依靠特定的认证服务（例如LDAP、RDBMS或基于文件的存储）来认证。不同的适配器可能有不同的选项和行为，但有些基本的事情是通用的。例如，接受认证证书（包括声称实体）、认证、返回一些结果在Zend_Auth适配器中是通用的。

每个Zend_Auth 认证适配器类都实现`Zend_Auth_Adapter_Interface`.这个接口定义了一个方法，`authenticate()`, 适配器实现它来做认证。在调用`authenticate()`之前，每个适配器必需准备就绪。这就意味着每个适配器要提供设置证书（例如，用户名和密码）的能力并为适配器规范选项定义一些值，例如数据库表适配器的连接设置。

下面是一个认证适配器的例子，它要求为认证设置用户名和密码。为简明扼要，其它的细节（如查询认证服务）被省略了。

    <?php
    require_once 'Zend/Auth/Adapter/Interface.php';

    class MyAuthAdapter implements Zend_Auth_Adapter_Interface
    {
        /**
         * Sets username and password for authentication
         *
         * @return void
         */
        public function __construct($username, $password)
        {
            // ...
        }

        /**
         * Performs an authentication attempt
         *
         * @throws Zend_Auth_Adapter_Exception If authentication cannot be performed
         * @return Zend_Auth_Result
         */
        public function authenticate()
        {
            // ...
        }
    }

如上面所示，`authenticate()`必需返回一个`Zend_Auth_Result`的实例（或从`Zend_Auth_Result`派生的一个类）。如果因为某些原因认证查询不能执行，`authenticate()`应该抛出一个由`Zend_Auth_Adapter_Exception`产生的异常。

### 3.1.2. 结果

为了表示一个认证尝试的结果，Zend_Auth适配器返回一个带有`authenticate()`的`Zend_Auth_Result`的实例。适配器基于结构组成`Zend_Auth_Result`对象，下面三个方法提供了一组基本的通用Zend_Auth适配器结果的操作：

- `isValid()` - 返回 true 当且仅当结果表示一个成功的认证尝试

- `getIdentity()` - 返回认证尝试的身份

- `getMessages()` - 返回关于认证尝试失败的数组

### 3.1.3. 身份的持久（Persistence）

实质上，认证一个包含认证证书的请求很有用，但是维护已认证的身份并在每次请求时不需要出示认证证书也同样很重要。

HTTP是一个无连接的协议，然而，象cookie和session这样的技术已经被开发出来使在服务器端的web应用维护多请求状态变得容易。Zend_Session被Zend_Auth缺省地使用，它用PHP session为一个成功认证尝试的身份提供持久存储空间。

基于成功的认证尝试，`Zend_Auth::authenticate()` 把身份从认证结果存储到持久存储空间。缺省地，`Zend_Auth` 使用基于 Zend_Session 的存储类。存储类可以通过 `Zend_Auth::setStorage()` 提供不同的存储对象来被改变。

如果自动的身份持久存储对特定的用例来说不合适，那么开发者可以完全地放弃使用`Zend_Auth`，取而代之，直接使用适配器类。

### 3.1.4. 使用Zend_Auth

这里提供了两种方法使用Zend_Auth适配器：

1. 非直接地，通过`Zend_Auth::authenticate()`

2. 直接地，通过适配器的 `authenticate()` 方法

下面的例子通过`Zend_Auth`类来示例如何非直接地使用Zend_Auth适配器：

    <?php
    // Get a reference to the Singleton instance of Zend_Auth
    require_once 'Zend/Auth.php';
    $auth = Zend_Auth::getInstance();

    // Set up the authentication adapter
    $authAdapter = new MyAuthAdapter($username, $password);

    // Attempt authentication, saving the result
    $result = $auth->authenticate($authAdapter);

    if (!$result->isValid()) {
        // Authentication failed; print the reasons why
        foreach ($result->getMessages() as $message) {
            echo "$message\n";
        }
    } else {
        // Authentication succeeded; the identity ($username) is stored in the session
        // $result->getIdentity() === $auth->getIdentity()
        // $result->getIdentity() === $username
    }

一旦在一个请求里的认证被尝试，如上面的例子，检查一个成功的被认证的身份是否存在就是一个简单的匹配：

    <?php
    $auth = Zend_Auth::getInstance();
    if ($auth->hasIdentity()) {
        // Identity exists; get it
        $identity = $auth->getIdentity();
    }

从持久存储空间出去一个身份，可简单地使用`clearIdentity()`方法。这将被典型地用作“logout”操作。

    <?php
    Zend_Auth::getInstance()->clearIdentity();

当自动使用持久存储空间对特定的用例不合适，开发者可简单地忽略`Zend_Auth`类，直接使用适配器类。直接使用适配器类需要配置和准备适配器对象和调用它的`authenticate()`方法。适配器规范细节将在每个适配器的文档中讨论。下面的例子直接使用 `MyAuthAdapter`：

    <?php
    // Set up the authentication adapter
    $authAdapter = new MyAuthAdapter($username, $password);

    // Attempt authentication, saving the result
    $result = $authAdapter->authenticate();

    if (!$result->isValid()) {
        // Authentication failed; print the reasons why
        foreach ($result->getMessages() as $message) {
            echo "$message\n";
        }
    } else {
        // Authentication succeeded
        // $result->getIdentity() === $username
    }

上一页 |  | 下一页
2.3. 高级用法 | 起始页 | 3.2. 数字认证