<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Authentication\Adapter\DbTable;
use Zend\Authentication\Result as AuthenticationResult;
use Zend\Db\Adapter\Adapter as DbAdapter;
use Zend\Db\Sql;
use Zend\Db\Sql\Expression as SqlExpr;
use Zend\Db\Sql\Predicate\Operator as SqlOp;
class CredentialTreatmentAdapter extends AbstractAdapter
{
/**
* $credentialTreatment - Treatment applied to the credential, such as MD5() or PASSWORD()
*
* @var string
*/
protected $credentialTreatment = null;
/**
* __construct() - Sets configuration options
*
* @param DbAdapter $zendDb
* @param string $tableName Optional
* @param string $identityColumn Optional
* @param string $credentialColumn Optional
* @param string $credentialTreatment Optional
*/
public function __construct(
DbAdapter $zendDb,
$tableName = null,
$identityColumn = null,
$credentialColumn = null,
$credentialTreatment = null
) {
parent::__construct($zendDb, $tableName, $identityColumn, $credentialColumn);
if (null !== $credentialTreatment) {
$this->setCredentialTreatment($credentialTreatment);
}
}
/**
* setCredentialTreatment() - allows the developer to pass a parametrized string that is
* used to transform or treat the input credential data.
*
* In many cases, passwords and other sensitive data are encrypted, hashed, encoded,
* obscured, or otherwise treated through some function or algorithm. By specifying a
* parametrized treatment string with this method, a developer may apply arbitrary SQL
* upon input credential data.
*
* Examples:
*
* 'PASSWORD(?)'
* 'MD5(?)'
*
* @param string $treatment
* @return DbTable Provides a fluent interface
*/
public function setCredentialTreatment($treatment)
{
$this->credentialTreatment = $treatment;
return $this;
}
/**
* _authenticateCreateSelect() - This method creates a Zend\Db\Sql\Select object that
* is completely configured to be queried against the database.
*
* @return Sql\Select
*/
protected function authenticateCreateSelect()
{
// build credential expression
if (empty($this->credentialTreatment) || (strpos($this->credentialTreatment, '?') === false)) {
$this->credentialTreatment = '?';
}
$credentialExpression = new SqlExpr(
'(CASE WHEN ?' . ' = ' . $this->credentialTreatment . ' THEN 1 ELSE 0 END) AS ?',
array($this->credentialColumn, $this->credential, 'zend_auth_credential_match'),
array(SqlExpr::TYPE_IDENTIFIER, SqlExpr::TYPE_VALUE, SqlExpr::TYPE_IDENTIFIER)
);
// get select
$dbSelect = clone $this->getDbSelect();
$dbSelect->from($this->tableName)
->columns(array('*', $credentialExpression))
->where(new SqlOp($this->identityColumn, '=', $this->identity));
return $dbSelect;
}
/**
* _authenticateValidateResult() - This method attempts to validate that
* the record in the resultset is indeed a record that matched the
* identity provided to this adapter.
*
* @param array $resultIdentity
* @return AuthenticationResult
*/
protected function authenticateValidateResult($resultIdentity)
{
if ($resultIdentity['zend_auth_credential_match'] != '1') {
$this->authenticateResultInfo['code'] = AuthenticationResult::FAILURE_CREDENTIAL_INVALID;
$this->authenticateResultInfo['messages'][] = 'Supplied credential is invalid.';
return $this->authenticateCreateAuthResult();
}
unset($resultIdentity['zend_auth_credential_match']);
$this->resultRow = $resultIdentity;
$this->authenticateResultInfo['code'] = AuthenticationResult::SUCCESS;
$this->authenticateResultInfo['messages'][] = 'Authentication successful.';
return $this->authenticateCreateAuthResult();
}
}