There are three steps in the OpenID authentication procedure, and each
step is performed by a separate HTTP request. To store information
between requests, Zend_OpenId_Consumer uses internal storage.
Developers do not necessarily have to be aware of this storage because by default
Zend_OpenId_Consumer uses file-based storage under the temporary
directory- similar to PHP sessions. However, this storage may be not
suitable in all cases. Some developers may want to store information in a database,
while others may need to use common storage suitable for server farms. Fortunately,
developers may easily replace the default storage with their own. To specify a custom
storage mechanism, one need only extend the
Zend_OpenId_Consumer_Storage class and pass this subclass to the
Zend_OpenId_Consumer constructor in the first argument.
The following example demonstrates a simple storage mechanism that uses
Zend_Db as its backend and exposes three groups of functions.
The first group contains functions for working with associations, while the second group
caches discovery information, and the third group can be used to check whether a
response is unique. This class can easily be used with existing or new databases; if the
required tables don't exist, it will create them.
Example 628. Database Storage
<?php
class DbStorage extends Zend_OpenId_Consumer_Storage
{
private $_db;
private $_association_table;
private $_discovery_table;
private $_nonce_table;
// Pass in the Zend_Db_Adapter object and the names of the
// required tables
public function __construct($db,
$association_table = "association",
$discovery_table = "discovery",
$nonce_table = "nonce")
{
$this->_db = $db;
$this->_association_table = $association_table;
$this->_discovery_table = $discovery_table;
$this->_nonce_table = $nonce_table;
$tables = $this->_db->listTables();
// If the associations table doesn't exist, create it
if (!in_array($association_table, $tables)) {
$this->_db->getConnection()->exec(
"create table $association_table (" .
" url varchar(256) not null primary key," .
" handle varchar(256) not null," .
" macFunc char(16) not null," .
" secret varchar(256) not null," .
" expires timestamp" .
")");
}
// If the discovery table doesn't exist, create it
if (!in_array($discovery_table, $tables)) {
$this->_db->getConnection()->exec(
"create table $discovery_table (" .
" id varchar(256) not null primary key," .
" realId varchar(256) not null," .
" server varchar(256) not null," .
" version float," .
" expires timestamp" .
")");
}
// If the nonce table doesn't exist, create it
if (!in_array($nonce_table, $tables)) {
$this->_db->getConnection()->exec(
"create table $nonce_table (" .
" nonce varchar(256) not null primary key," .
" created timestamp default current_timestamp" .
")");
}
}
public function addAssociation($url,
$handle,
$macFunc,
$secret,
$expires)
{
$table = $this->_association_table;
$secret = base64_encode($secret);
$this->_db->insert($table, array(
'url' => $url,
'handle' => $handle,
'macFunc' => $macFunc,
'secret' => $secret,
'expires' => $expires,
));
return true;
}
public function getAssociation($url,
&$handle,
&$macFunc,
&$secret,
&$expires)
{
$table = $this->_association_table;
$this->_db->delete(
$table, $this->_db->quoteInto('expires < ?', time())
);
$select = $this-_db->select()
->from($table, array('handle', 'macFunc', 'secret', 'expires'))
->where('url = ?', $url);
$res = $this->_db->fetchRow($select);
if (is_array($res)) {
$handle = $res['handle'];
$macFunc = $res['macFunc'];
$secret = base64_decode($res['secret']);
$expires = $res['expires'];
return true;
}
return false;
}
public function getAssociationByHandle($handle,
&$url,
&$macFunc,
&$secret,
&$expires)
{
$table = $this->_association_table;
$this->_db->delete(
$table, $this->_db->quoteInto('expires < ', time())
);
$select = $this->_db->select()
->from($table, array('url', 'macFunc', 'secret', 'expires')
->where('handle = ?', $handle);
$res = $select->fetchRow($select);
if (is_array($res)) {
$url = $res['url'];
$macFunc = $res['macFunc'];
$secret = base64_decode($res['secret']);
$expires = $res['expires'];
return true;
}
return false;
}
public function delAssociation($url)
{
$table = $this->_association_table;
$this->_db->query("delete from $table where url = '$url'");
return true;
}
public function addDiscoveryInfo($id,
$realId,
$server,
$version,
$expires)
{
$table = $this->_discovery_table;
$this->_db->insert($table, array(
'id' => $id,
'realId' => $realId,
'server' => $server,
'version' => $version,
'expires' => $expires,
));
return true;
}
public function getDiscoveryInfo($id,
&$realId,
&$server,
&$version,
&$expires)
{
$table = $this->_discovery_table;
$this->_db->delete($table, $this->quoteInto('expires < ?', time()));
$select = $this->_db->select()
->from($table, array('realId', 'server', 'version', 'expires'))
->where('id = ?', $id);
$res = $this->_db->fetchRow($select);
if (is_array($res)) {
$realId = $res['realId'];
$server = $res['server'];
$version = $res['version'];
$expires = $res['expires'];
return true;
}
return false;
}
public function delDiscoveryInfo($id)
{
$table = $this->_discovery_table;
$this->_db->delete($table, $this->_db->quoteInto('id = ?', $id));
return true;
}
public function isUniqueNonce($nonce)
{
$table = $this->_nonce_table;
try {
$ret = $this->_db->insert($table, array(
'nonce' => $nonce,
));
} catch (Zend_Db_Statement_Exception $e) {
return false;
}
return true;
}
public function purgeNonces($date=null)
{
}
}
$db = Zend_Db::factory('Pdo_Sqlite',
array('dbname'=>'/tmp/openid_consumer.db'));
$storage = new DbStorage($db);
$consumer = new Zend_OpenId_Consumer($storage);
This example doesn't list the OpenID authentication code itself, but this code would be the same as that for other examples in this chapter. examples.




