PhpRiot
Become Zend Certified

Prepare for the ZCE exam using our quizzes (web or iPad/iPhone). More info...


When you're ready get 7.5% off your exam voucher using voucher CJQNOV23 at the Zend Store

Zend_OpenId_Consumer_Storage

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 646. 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.

Zend Framework