3.2. 用数据库表认证

3.2.1. 简介

Zend_Auth_Adapter_DbTable提供依靠存储在数据库表中的证书来认证的能力。因为Zend_Auth_Adapter_DbTable需要Zend_Db_Adapter_Abstract的实例来传递给它的构造器,所以每个实例要和特定的数据库连接绑定。其它配置选项可以通过构造器和实例方法设置,每个选项有一个配置。

可用的配置选项包括:

  • tableName: 包含认证证书的数据库表名,执行数据库认证查询需要依靠这个证书。

  • identityColumn: 数据库表的列的名称,用来表示身份。身份列必须包含唯一的值,例如用户名或者e-mail地址。

  • credentialColumn: 数据库表的列的名称,用来表示证书。在一个简单的身份和密码认证scheme下,证书的值对应为密码。参见 credentialTreatment 选项。

  • credentialTreatment: 在许多情况下,密码和其他敏感数据是加密的(encrypted, hashed, encoded, obscured 或者通过以下函数或算法来加工)。通过指定参数化的字串来使用这个方法,例如'MD5(?)' 或者 'PASSWORD(?)',开发者可以在输入证书数据时使用任意的SQL。因为这些函数对其下面的RDBMS是专用的, 请查看数据库手册来确保你所用的数据库的函数的可用性。

例 3.3. 基本用法

正如在简介中所解释的,Zend_Auth_Adapter_DbTable构造器需要一个Zend_Db_Adapter_Abstract的实例,这个实例用做数据库连结,并且认证适配器实例绑定到这个数据库连接。首先,应该创建数据库连接。

下面的代码为in-memory数据库创建一个适配器,创建一个简单的表schema,并插入我们将来可以执行认证查询的一行(数据)。这个例子需要PDO SQLite extension可用。

<?php
// 创建一个 in-memory SQLite 数据库连接
require_once 'Zend/Db/Adapter/Pdo/Sqlite.php';
$dbAdapter = new Zend_Db_Adapter_Pdo_Sqlite(array('dbname' => ':memory:'));

// 构造一个简单表的创建语句
$sqlCreate = 'CREATE TABLE [users] ( '
           . '[id] INTEGER  NOT NULL PRIMARY KEY, '
           . '[username] VARCHAR(50) UNIQUE NOT NULL, '
           . '[password] VARCHAR(32) NULL, '
           . '[real_name] VARCHAR(150) NULL)';

// 创建认证证书表
$dbAdapter->query($sqlCreate);

// 构造用来插入一行可以成功认证的数据的语句
$sqlInsert = 'INSERT INTO users (username, password, real_name) '
           . 'VALUES ("my_username", "my_password", "My Real Name")';

// 插入数据
$dbAdapter->query($sqlInsert);

随着数据库连接和表数据已经可用,Zend_Auth_Adapter_DbTable可以被创建。配置选项的值可以传递给构造器或者延后在实例化以后用做setter方法的参数。

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

// 用构造器参数来配置实例...
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter, 'users', 'username', 'password');

// ...或用 setter 方法配置实例
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('users')
            ->setIdentityColumn('username')
            ->setCredentialColumn('password');

在这点上,认证适配器实例已经可以接受认证查询。为了合成一个认证查询,在调用authenticate()方法之前,输入的证书的值要传递给适配器:

<?php
// 设置输入的证书的值(例如,从登陆的表单)
$authAdapter->setIdentity('my_username')
            ->setCredential('my_password');

// 执行认证查询,并保存结果
$result = $authAdapter->authenticate();

除了基于认证结果对象的 getIdentity() 方法的可用性之外,Zend_Auth_Adapter_DbTable也支持从认证成功的表中读取一行数据:

<?php
// 输出身份
echo $result->getIdentity() . "\n\n";

// 输出结果行
print_r($identity);

/* Output:
my_username

Array
(
    [id] => 1
    [username] => my_username
    [password] => my_password
    [real_name] => My Real Name
)
*/

因为表行里包含证书值,通过防止无意识地访问来安全化这个值很重要。

3.2.2. 高级使用:持久一个 DbTable 结果对象

缺省地,基于成功的认证Zend_Auth_Adapter_DbTable 返回提供给auth对象的身份。其他用例情景,开发者想给Zend_Auth 的持久存储机制存储一个包括其他有用信息的身份对象,已经通过使用getResultRowObject() 方法返回一个stdClass对象解决了。下面的代码片段举例说明它的用法:

<?php
// authenticate with Zend_Auth_Adapter_DbTable
$result = $this->_auth->authenticate($adapter);

if ($result->isValid()) {

    // store the identity as an object where only the username and real_name have been returned
    $this->_auth->getStorage()->write($adapter->getResultRowObject(array('username', 'real_name'));

    // store the identity as an object where the password column has been omitted
    $this->_auth->getStorage()->write($adapter->getResultRowObject(null, 'password'));

    /* ... */

} else {

    /* ... */

}