Tabla de base de datos de autenticación
Introducción
Zend_Auth_Adapter_DbTable proporciona la capacidad
de autenticar contra credenciales almacenadas en una tabla de la base de
datos. Como Zend_Auth_Adapter_DbTable requiere una
instancia de Zend_Db_Adapter_Abstract que será
pasada a su constructor, cada instancia está vinculada a una conexión
concreta de la base de datos. Se pueden establecer otras opciones de
configuración a través del constructor y de métodos de instancia:
Las opciones de configuración disponibles incluyen:
tableName: Nombre de tabla de la base de datos que
contiene las credenciales de autenticación, y contra la cual
se realiza la búsqueda de autenticación en la base de datos.
identityColumn: Nombre de la columna de la tabla
de la base de datos utilizada para representar la identidad. La
columna identidad debe contar con valores únicos, tales como un
apellido ó una dirección de e-mail.
credentialColumn: Nombre de la columna de la tabla
de la base de datos utilizada para representar la credencial.
Conforme a un sistema de identidad simple y autenticación de
contraseña, el valor de la credencial corresponde con la
contraseña. Véase también la opción credentialTreatment
.
credentialTreatment: En muchos casos, contraseñas
y otros datos son encriptados, mezclados, codificados,
ocultados, desplazados o tratados de otra manera a través de
alguna función o algoritmo. Al especificar una cadena de
tratamiento parametrizada con este método, tal como
'MD5(?)' o 'PASSWORD(?)', un
desarrollador podría aplicar sentencias arbitrarias SQL
sobre los datos credenciales de entrada. Ya que estas funciones
son específicas de los RDBMS, debemos consultar el manual de la
base de datos para comprobar la disponibilidad de tales
funciones para su sistema de base de datos.
Uso Básico
Como se explicó en la introducción, el constructor
Zend_Auth_Adapter_DbTable requiere una instancia
de Zend_Db_Adapter_Abstract que sirve como
conexión a la base de datos a la cual la instancia de autenticación
está obligada a adaptarse. En primer lugar, la conexión de la base de
datos debe ser creada.
El siguiente código crea un adaptador para una base de datos en memoria
, un esquema simple de la tabla, e inserta una fila contra la que se
pueda realizar una consulta de autenticación posterior. Este ejemplo
requiere que la extensión DOP SQLite esté disponible.
':memory:'));
// Construir mediante una consulta una simple tabla
$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)';
// Crear las credenciales de autenticación de la tabla
$dbAdapter->query($sqlCreate);
// Construir una consulta para insertar una fila para que se pueda realizar la autenticación
$sqlInsert = "INSERT INTO users (username, password, real_name) "
. "VALUES ('my_username', 'my_password', 'My Real Name')";
// Insertar los datos
$dbAdapter->query($sqlInsert);
]]>
Con la conexión de la base de datos y los datos de la tabla
disponibles, podemos crear un instancia de
Zend_Auth_Adapter_DbTable. Los valores de las opciones
de configuración pueden ser pasados al constructor o pasados como
parámetros a los métodos setter después de ser instanciados.
setTableName('users')
->setIdentityColumn('username')
->setCredentialColumn('password')
;
]]>
En este punto, el adaptador de la instancia de autenticación está listo
para aceptar consultas de autenticación. Con el fin de elaborar una
consulta de autenticación, los valores de entrada de la credencial son
pasados por el adaptador ates de llamar al método
authenticate():
setIdentity('my_username')
->setCredential('my_password')
;
// Ejecutamos la consulta de autenticación, salvando los resultados
]]>
Además de la disponibilidad del método getIdentity()
sobre el objeto resultante de la autenticación,
Zend_Auth_Adapter_DbTable también ayuda a
recuperar la fila de al tabla sobre la autenticación realizada.
getIdentity() . "\n\n";
// Imprimir la fila resultado
print_r($authAdapter->getResultRowObject());
/* Salida:
my_username
Array
(
[id] => 1
[username] => my_username
[password] => my_password
[real_name] => My Real Name
)
]]>
Ya que la fila de la tabla contiene el valor de la credencial, es
importante proteger los valores contra accesos no deseados.
Advanced Usage: Manteniendo el resultado del Objeto DbTable
Por defecto, Zend_Auth_Adapter_DbTable devuelve la
identidad proporcionada al objeto Auth en la autenticación
realizada. Otro de los casos de uso, donde los desarrolladores desean
guardar para mantener el mecanismo de almacenamiento de un objeto identidad
Zend_Auth que contiene información útil, se
resuelve usando el método getResultRowObject() para devolver
un objeto stdClass. El siguiente fragmento de código muestra
su uso:
_auth->authenticate($adapter);
if ($result->isValid()) {
// Almacena la identidad como un objedo dónde solo username y
// real_name han sido devueltos
$storage = $this->_auth->getStorage();
$storage->write($adapter->getResultRowObject(array(
'username',
'real_name',
)));
// Almacena la identidad como un objeto dónde la columna contraseña ha
// sido omitida
$storage->write($adapter->getResultRowObject(
null,
'password'
));
/* ... */
} else {
/* ... */
}
]]>
Ejemplo de Uso Avanzado
Si bien el objetivo primordial de Zend_Auth (y,
por consiguiente, Zend_Auth_Adapter_DbTable) es
principalmente la autenticación y no
la autorización, hay unos pocos casos
y problemas que se encuentran al límite entre cuales encajan dentro del
dominio.
Dependiendo de cómo haya decidido explicar su problema, a veces tiene
sentido resolver lo que podría parecer un problema de autorización
dentro de un adaptador de autenticación.
Con esa excepción fuera de lo común,
Zend_Auth_Adapter_DbTable ha construido mecanismos
que pueden ser aprovechados para realizar controles adicionales en la
autenticación a la vez que se resuelven algunos problemas comunes de los
usuarios.
Otra idea puede ser la aplicación de un mecanismo de "salting". "Salting"
es un término que se refiere a una técnica que puede mejorar altamente la
seguridad de su aplicación. Se basa en la idea de concatenar una cadena
aleatoria a cada contraseña para evitar un ataque de fuerza bruta sobre la
base de datos usando los valores hash de un diccionario pre-calculado.
Por lo tanto, tenemos que modificar nuestra tabla para almacenar nuestra
cadena mezclada:
Aquí hay una forma sencilla de generar una cadena mezclada por cada
usuario en el momento del registro:
Y ahora vamos a construir el adaptador:
Puede mejorar aún más la seguridad mediante el uso de un valor
'salt' estático fuertemente codificado en su aplicación. En el caso de
que su base de datos se vea comprometida (por ejemplo, por un ataque
de inyección SQL), su servidor web está intacto y sus
datos son inutilizable para el atacante.
Otra alternativa es utilizar el método getDbSelect() de
Zend_Auth_Adapter_DbTable después de que el adaptador se ha construido.
Este método devolverá la instancia del objeto Zend_Db_Select que se va a
utilizar para completar la rutina de authenticate(). Es importante señalar
que este método siempre devuelve el mismo objeto, independientemente de si
authenticate() ha sido llamado o no. Este objeto
no tendrá ninguna de las
credenciales de identidad o información de como estos valores son colocados
dentro del objeto seleccionado en authenticate().
Un ejemplo de una situación en la que uno podría querer utilizar el
método getDbSelect() sería comprobar el estado de un usuario, en otras
palabras, ver si la cuenta del usuario está habilitada.
getDbSelect();
$select->where('active = "TRUE"');
// authenticate, esto asegura que users.active = TRUE
$adapter->authenticate();
]]>