Tabla de contenidos
- 41.1. Introducción
- 41.2. Resumen de la API
- 41.3. Escenarios de uso
- 41.4. Herramientas
- 41.5. Acceso orientado a objetos al árbol LDAP usando Zend_Ldap_Node
- 41.6. Obtener información del servidor LDAP
- 41.7. Serializar datos LDAP hacia y desde LDIF
Zend_Ldap es una clase para realizar operaciones LDAP
que incluyen, entre otras, el enlace (binding), la búsqueda y la modificación de entradas
en un directorio LDAP.
Este componente consiste actualmente en la clase principal Zend_Ldap,
que representa conceptualmente un enlace a un único servidor LDAP
y permite ejecutar operaciones contra un servidor LDAP como
OpenLDAP o servidores ActiveDirectory (AD). Los parámetros para el enlace pueden
proporcionarse explícitamente o en forma de un array de opciones.
Zend_Ldap_Node proporciona una interfaz orientada a objetos
para nodos LDAP individuales y puede usarse para formar la base de una
interfaz similar a un registro activo para un modelo de dominio basado en LDAP.
El componente proporciona varias clases auxiliares para realizar operaciones en
entradas LDAP (Zend_Ldap_Attribute) tales como
establecer y recuperar atributos (valores de fecha, contraseñas, valores booleanos, ...), para
crear y modificar cadenas de filtro LDAP
(Zend_Ldap_Filter) y para manipular nombres distinguidos (DN)
de LDAP (Zend_Ldap_Dn).
Adicionalmente el componente abstrae la exploración de esquemas LDAP
para servidores OpenLDAP y ActiveDirectoy Zend_Ldap_Node_Schema
y la recuperación de información del servidor para servidores OpenLDAP, ActiveDirectory y Novell
eDirectory (Zend_Ldap_Node_RootDse).
El uso de la clase Zend_Ldap depende del tipo de
servidor LDAP y se resume mejor con algunos ejemplos sencillos.
Si está usando OpenLDAP, un ejemplo sencillo se ve como sigue (tenga en cuenta que la opción bindRequiresDn es importante si no está usando AD):
$options = array(
'host' => 's0.foo.net',
'username' => 'CN=user1,DC=foo,DC=net',
'password' => 'pass1',
'bindRequiresDn' => true,
'accountDomainName' => 'foo.net',
'baseDn' => 'OU=Sales,DC=foo,DC=net',
);
$ldap = new Zend_Ldap($options);
$acctname = $ldap->getCanonicalAccountName('abaker',
Zend_Ldap::ACCTNAME_FORM_DN);
echo "$acctname\n";
Si está usando Microsoft AD un ejemplo sencillo es:
$options = array(
'host' => 'dc1.w.net',
'useStartTls' => true,
'username' => 'user1@w.net',
'password' => 'pass1',
'accountDomainName' => 'w.net',
'accountDomainNameShort' => 'W',
'baseDn' => 'CN=Users,DC=w,DC=net',
);
$ldap = new Zend_Ldap($options);
$acctname = $ldap->getCanonicalAccountName('bcarter',
Zend_Ldap::ACCTNAME_FORM_DN);
echo "$acctname\n";
Tenga en cuenta que usamos el método getCanonicalAccountName()
para recuperar el DN de la cuenta aquí solamente porque es lo que ejercita
la mayor parte del poco código actualmente presente en esta clase.
Si se llama a bind() con un nombre de usuario que no es un DN pero
bindRequiresDN es TRUE y no se proporcionó ningún nombre de usuario en
forma de DN como opción, el enlace fallará. Sin embargo, si se proporciona un nombre de usuario en forma
de DN en el array de opciones, Zend_Ldap
primero se enlazará con ese nombre de usuario, recuperará el DN de la cuenta para el nombre de usuario
proporcionado a bind() y luego se volverá a enlazar con ese DN.
Este comportamiento es crítico para Zend_Auth_Adapter_Ldap,
que pasa el nombre de usuario proporcionado por el usuario directamente a
bind().
El siguiente ejemplo ilustra cómo el nombre de usuario que no es un DN
'abaker' puede usarse con bind():
$options = array(
'host' => 's0.foo.net',
'username' => 'CN=user1,DC=foo,DC=net',
'password' => 'pass1',
'bindRequiresDn' => true,
'accountDomainName' => 'foo.net',
'baseDn' => 'OU=Sales,DC=foo,DC=net',
);
$ldap = new Zend_Ldap($options);
$ldap->bind('abaker', 'moonbike55');
$acctname = $ldap->getCanonicalAccountName('abaker',
Zend_Ldap::ACCTNAME_FORM_DN);
echo "$acctname\n";
La llamada a bind() en este ejemplo ve que
el nombre de usuario 'abaker' no está en forma de DN, encuentra que
bindRequiresDn es TRUE, usa
'CN=user1,DC=foo,DC=net' y 'pass1' para
enlazar, recupera el DN de 'abaker', desenlaza y luego vuelve a enlazar
con el recién descubierto
'CN=Alice Baker,OU=Sales,DC=foo,DC=net'.
Las opciones accountDomainName y accountDomainNameShort se usan para dos propósitos: (1) facilitan la capacidad de autenticación multidominio y conmutación por error, y (2) también se usan para canonicalizar los nombres de usuario. Específicamente, los nombres se canonicalizan a la forma especificada por la opción accountCanonicalForm. Esta opción puede ser uno de los siguientes valores:
Tabla 41.1. Opciones para accountCanonicalForm
| Nombre | Valor | Ejemplo |
|---|---|---|
ACCTNAME_FORM_DN |
1 | CN=Alice Baker,CN=Users,DC=example,DC=com |
ACCTNAME_FORM_USERNAME |
2 | abaker |
ACCTNAME_FORM_BACKSLASH |
3 | EXAMPLE\abaker |
ACCTNAME_FORM_PRINCIPAL |
4 | abaker@example.com |
La canonicalización predeterminada depende de qué opciones de nombre de dominio de cuenta se hayan
proporcionado. Si se proporcionó accountDomainNameShort, el
valor predeterminado de accountCanonicalForm es
ACCTNAME_FORM_BACKSLASH. De lo contrario, si se proporcionó
accountDomainName, el
valor predeterminado es ACCTNAME_FORM_PRINCIPAL.
La canonicalización del nombre de cuenta garantiza que la cadena usada para identificar
una cuenta sea consistente independientemente de lo que se haya proporcionado a
bind(). Por ejemplo, si el usuario proporciona un nombre de cuenta
de abaker@example.com o simplemente
abaker y accountCanonicalForm
se establece en 3, el nombre canonicalizado resultante sería
EXAMPLE\abaker.
El componente Zend_Ldap por sí mismo no intenta
autenticarse con múltiples servidores. Sin embargo, Zend_Ldap
está diseñado específicamente para manejar este escenario con elegancia. La
técnica requerida es simplemente iterar sobre un array de arrays de opciones
de servidor e intentar enlazar con cada servidor. Como se describió anteriormente,
bind() canonicalizará automáticamente cada nombre, por lo que
no importa si el usuario pasa abaker@foo.net o
W\bcarter o cdavis: el
método bind() solo tendrá éxito si las credenciales se
usaron correctamente en el enlace.
Considere el siguiente ejemplo que ilustra la técnica requerida para implementar autenticación multidominio y conmutación por error:
$acctname = 'W\\user2';
$password = 'pass2';
$multiOptions = array(
'server1' => array(
'host' => 's0.foo.net',
'username' => 'CN=user1,DC=foo,DC=net',
'password' => 'pass1',
'bindRequiresDn' => true,
'accountDomainName' => 'foo.net',
'accountDomainNameShort' => 'FOO',
'accountCanonicalForm' => 4, // ACCT_FORM_PRINCIPAL
'baseDn' => 'OU=Sales,DC=foo,DC=net',
),
'server2' => array(
'host' => 'dc1.w.net',
'useSsl' => true,
'username' => 'user1@w.net',
'password' => 'pass1',
'accountDomainName' => 'w.net',
'accountDomainNameShort' => 'W',
'accountCanonicalForm' => 4, // ACCT_FORM_PRINCIPAL
'baseDn' => 'CN=Users,DC=w,DC=net',
),
);
$ldap = new Zend_Ldap();
foreach ($multiOptions as $name => $options) {
echo "Trying to bind using server options for '$name'\n";
$ldap->setOptions($options);
try {
$ldap->bind($acctname, $password);
$acctname = $ldap->getCanonicalAccountName($acctname);
echo "SUCCESS: authenticated $acctname\n";
return;
} catch (Zend_Ldap_Exception $zle) {
echo ' ' . $zle->getMessage() . "\n";
if ($zle->getCode() === Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH) {
continue;
}
}
}
Si el enlace falla por cualquier motivo, se intenta con el siguiente conjunto de opciones de servidor.
La llamada a getCanonicalAccountName() obtiene el nombre de cuenta canónico
que la aplicación presumiblemente usaría para asociar datos, como
las preferencias. El accountCanonicalForm = 4 en todas las opciones
de servidor garantiza que la forma canónica sea consistente independientemente de qué
servidor se haya usado finalmente.
La excepción especial LDAP_X_DOMAIN_MISMATCH ocurre cuando se proporcionó un
nombre de cuenta con un componente de dominio (por ejemplo,
abaker@foo.net o FOO\abaker y no solamente
abaker) pero el componente de dominio no coincidió con ninguno de los dominios
en las opciones de servidor actualmente seleccionadas. Esta excepción indica
que el servidor no es una autoridad para la cuenta. En este
caso, el enlace no se realizará, eliminando así la comunicación innecesaria
con el servidor. Tenga en cuenta que la instrucción continue
no tiene efecto en este ejemplo, pero en la práctica, por motivos de manejo de errores y
depuración, probablemente querrá comprobar
LDAP_X_DOMAIN_MISMATCH así como
LDAP_NO_SUCH_OBJECT y
LDAP_INVALID_CREDENTIALS.
El código anterior es muy similar al código usado dentro de Zend_Auth_Adapter_Ldap.
De hecho, recomendamos que simplemente use ese adaptador de autenticación para
la autenticación LDAP multidominio + conmutación por error
(o copie el código).