Autenticación en PHP usando LDAP a través de Active Directory

104

Estoy buscando una forma de autenticar usuarios a través de LDAP con PHP (con Active Directory como proveedor). Idealmente, debería poder ejecutarse en IIS 7 ( adLDAP lo hace en Apache). ¿Alguien había hecho algo similar, con éxito?

  • Editar: Preferiría una biblioteca / clase con código que esté listo para funcionar ... Sería una tontería inventar la rueda cuando alguien ya lo ha hecho.
DV.
fuente
Creo que drupal tiene un módulo para eso
redben

Respuestas:

167

Importar una biblioteca completa parece ineficaz cuando todo lo que necesita son esencialmente dos líneas de código ...

$ldap = ldap_connect("ldap.example.com");
if ($bind = ldap_bind($ldap, $_POST['username'], $_POST['password'])) {
  // log them in!
} else {
  // error message
}
ceejayoz
fuente
43
Algunas instalaciones de AD se vincularán correctamente si la contraseña proporcionada está vacía. ¡Se cuidadoso con esto! Es posible que deba asegurarse de que la contraseña no esté vacía antes de intentar autenticarse.
diolemo
@diolemo ¿Hay alguna forma de evitar esto sin verificar si la contraseña está vacía?
Naftali alias Neal
@Neal Es posible que pueda utilizar ldap_set_optionpara hacer que se comporte de una manera diferente. ¿Quizás establecer la versión del protocolo? Tendrás que experimentar. Personalmente, le sugiero que busque una contraseña vacía de todos modos, solo para estar seguro.
diolemo
Para el editor anónimo: no, que yo sepa, la desinfección de entrada no es necesaria aquí como ldap_bindlo sería manejarla y los caracteres especiales no son un problema.
ceejayoz
14

Pensaría que simplemente autenticar a un usuario en Active Directory sería un proceso bastante simple usando LDAP en PHP sin la necesidad de una biblioteca. Pero hay muchas cosas que pueden complicarlo bastante rápido:

  • Debe validar la entrada. De lo contrario, pasaría un nombre de usuario / contraseña vacío.
  • Debe asegurarse de que el nombre de usuario / contraseña esté codificado correctamente al realizar el enlace.
  • Debería cifrar la conexión mediante TLS.
  • Usar servidores LDAP separados para redundancia en caso de que uno no funcione.
  • Recibiendo un mensaje de error informativo si falla la autenticación.

De hecho, en la mayoría de los casos es más fácil utilizar una biblioteca LDAP que admita lo anterior. Finalmente terminé lanzando mi propia biblioteca que maneja todos los puntos anteriores: LdapTools (Bueno, no solo para la autenticación, puede hacer mucho más). Se puede usar de la siguiente manera:

use LdapTools\Configuration;
use LdapTools\DomainConfiguration;
use LdapTools\LdapManager;

$domain = (new DomainConfiguration('example.com'))
    ->setUsername('username') # A separate AD service account used by your app
    ->setPassword('password')
    ->setServers(['dc1', 'dc2', 'dc3'])
    ->setUseTls(true);
$config = new Configuration($domain);
$ldap = new LdapManager($config);

if (!$ldap->authenticate($username, $password, $message)) {
    echo "Error: $message";
} else {
    // Do something...
}

La llamada de autenticación anterior:

  • Valide que ni el nombre de usuario ni la contraseña estén vacíos.
  • Asegúrese de que el nombre de usuario / contraseña esté codificado correctamente (UTF-8 por defecto)
  • Pruebe con un servidor LDAP alternativo en caso de que uno no funcione.
  • Cifre la solicitud de autenticación mediante TLS.
  • Proporcione información adicional si falló (es decir, cuenta bloqueada / deshabilitada, etc.)

También hay otras bibliotecas para hacer esto (como Adldap2). Sin embargo, me sentí lo suficientemente obligado a proporcionar información adicional ya que la respuesta más votada es en realidad un riesgo de seguridad en el que confiar sin validación de entrada y sin usar TLS.

ChadSikorra
fuente
1
Para las conexiones LDAP, TLS se ha desaprobado en favor de StartTLS: openldap.org/faq/data/cache/605.html .
zenlord
2
@zenlord El uso del ldaps://formato para la conexión está en desuso. En mi ejemplo, cuando especifica setUseTls(true), usa ldap://formato y luego emite un StartTLS usando ldap_start_tls($connection). Por lo tanto, TLS en sí no se ha desaprobado, solo se conecta usando ldaps://(que en realidad se conecta a LDAP a través de un puerto completamente diferente).
ChadSikorra
12

Hago esto simplemente pasando las credenciales de usuario a ldap_bind ().

http://php.net/manual/en/function.ldap-bind.php

Si la cuenta se puede vincular a LDAP, es válida; si no puede, no lo es. Si todo lo que está haciendo es autenticación (no administración de cuentas), no veo la necesidad de una biblioteca.

Scott Reynen
fuente
9

Me gusta la clase Zend_Ldap , puede usar solo esta clase en su proyecto, sin Zend Framework.

CMS
fuente
1
Me tomé la molestia de implementar lo anterior y descubrí que era para administrar no autenticar. Tengo la intención de cambiar a zend.auth.adapter.ldap
vdidxho