En un post anterior titulado Control de sesiones – Autenticación de usuarios usando PHP y MySQL, se habló referente a cómo realizar un inicio de sesión que se autentique contra un tabla de usuarios en mysql y éste cree una sesión para éste usuario, de tal manera que nuestra aplicación esté protegida mediante ésta sesión y, cuando el usuario se salga del aplicativo web, se destruya la sesión. Bien, en ésta entrada veremos otra opción de autenticación; en lugar de una tabla en mysql, podemos usar Active Directory de un Windows Server (probado con versión 2000, 2003, 2008 y 2012). Si desean saber cómo gestionar los usuarios, ver la entrada: Uso básico de Active Directory – Windows Server.
Bien, un poco de teoría:
¿Qué es Active Directory? Implementación de un servicio de directorio en una red distribuida de computadores; almacena y organiza la información sobre los usuarios de una red de computadoras, sobre recursos de red, y permite a los administradores gestionar el acceso de usuarios a los recursos sobre dicha red.
Yo lo veo (puntualmente hablando) como una base de datos de usuarios, grupos de usuarios, computadoras, etc. de tal manera nos pueda servir para centralizar la autenticación de los usuarios y aplicar políticas a nivel de dominio.
Ahora, a lo que venimos… El requisito que necesitamos es que nuestra instalación PHP tenga la extensión o librerías que soporte LDAP. Como soy bastante «Linuxero», éste tutorial va enfocado para Ubuntu, pero para Windows es la misma lógica. Para los que tengan duda de PHP… Se recuerdan de la tecnología LAMP?
Instalando ldap en php. Nos vamos a una terminal y digitamos:
sudo apt-get install php5-ldap
Esto nos instalará la extensión de php necesaria para poder conectarnos a un servidor ldap (en nuestro caso, un Active Directory!). En Windows, hay que descomentariar la extensión de ldap, o sea «extension = php_ldap.dll» y la DLL (dependiendo de qué se usa… si XAMPP, AppServ, etc.) debería de tener la dll o igual.. hay que buscarla, copiarla en el lugar de las extensiones de php y reiniciar apache.
Para ver que ya esta funcionando, solo se crean un archivito en su carpeta de publicaciones (/var/www/html) con un nombre y extensión php (info.php por ejemplo) y adentro le ponen: <?php phpinfo(); ?>
Al ver en el navegador (http://localhost/info.php) deberían de encontrar un apartado LDAP
Ahora, vamos con la programación 😀
NOTA!!!: En éste código me enfocaré netamente en la conexión LDAP, NO estoy tocando temas como la seguridad, validación de campos, estética, etc.
1. Creamos nuestro archivo index.php y lo colocamos en la carpeta donde publicamos nuestro sitio. Al archivo index.php le colocamos el siguiente código.
<?php @session_start(); ?> <html> <head> <title>Acceso por LDAP</title> <body> <form method="post" action="control.php"><br> <table> <tr> <td>Usuario:</td> <td><input type="text" maxlength="50" name="usuario" id="usuario" /></td> </tr> <tr> <td>Clave:</td> <td><input type="password" maxlength="50" name="clave" id="clave" /> </td> </tr> <tr> <td colspan="2"><input type="submit" value="Entrar"></td> </tr> </table><br> </form> </body> </html> <?php exit(); ?>
Como pueden ver, es nuestra página inicio donde solicitamos el típico usuario y contraseña. Creo que no hay mucho que explicar… es casi HTML puro, solo hay un pequeño código php que hace referencia a la creación o reanudación de una sesión.
2. Ahora, crearemos nuestro archivo control.php el cual nos servirá para poder realizar el control de la autenticación. Tecleamos lo siguiente:
<?php require("ldap.php"); header("Content-Type: text/html; charset=utf-8"); $usr = $_POST["usuario"]; $usuario = mailboxpowerloginrd($usr,$_POST["clave"]); if($usuario == "0" || $usuario == ''){ $_SERVER = array(); $_SESSION = array(); echo"<script> alert('Usuario o clave incorrecta. Vuelva a digitarlos por favor.'); window.location.href='index.php'; </script>"; }else{ session_start(); $_SESSION["user"] = $usuario; $_SESSION["autentica"] = "SIP"; echo"<script>window.location.href='app.php'; </script>"; } ?>
Como se puede ver en el código, incluímos un archivo llamado ldap.php, que es el que hace la conexión hacia Active Directory. Luego capturamos el nombre de usuario y la clave (que vienen del Index.php por POST) y hacemos referencia a una función que esta en ldap.php para poder verificar que el usuario y contraseña enviados concuerda con la información en el AD. Luego, se verifica si retorna la función un 0 (no se logró autenticar) o un 1 (si se logró autenticar), para así guardar las variables de sesión respectivas o no. Al final, se redirecciona a la página respectiva dependiendo del resultado de la autenticación.
3. Veamos entonces el código del archivo ldap.php
<?php require_once("config.php"); function mailboxpowerloginrd($user,$pass){ $ldaprdn = trim($user).'@'.DOMINIO; $ldappass = trim($pass); $ds = DOMINIO; $dn = DN; $puertoldap = 389; $ldapconn = ldap_connect($ds,$puertoldap); ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION,3); ldap_set_option($ldapconn, LDAP_OPT_REFERRALS,0); $ldapbind = @ldap_bind($ldapconn, $ldaprdn, $ldappass); if ($ldapbind){ $filter="(|(SAMAccountName=".trim($user)."))"; $fields = array("SAMAccountName"); $sr = @ldap_search($ldapconn, $dn, $filter, $fields); $info = @ldap_get_entries($ldapconn, $sr); $array = $info[0]["samaccountname"][0]; }else{ $array=0; } ldap_close($ldapconn); return $array; } ?>
Lo primero que se hace es incluir un archivo de configuración en donde tenemos nuestras constantes, por ejemplo el nombre de dominio y DN. Luego, lo demás del código es para verificar si el usuario y la clave concuerdan con las del Active Directory.
4. El archivo config.php que tiene las constantes de nuestro dominio, contiene el siguiente código:
<?php define('DOMINIO', 'midominio.com.sv'); define('DN', 'dc=midominio,dc=com,dc=sv'); ?>
Obviamente, el servidor web debería estar en la misma red donde esta el dominio para que pueda llegar a él mediante su registro DNS. OJO!, deberán de cambiar el nombre de dominio (midominio.com.sv) por el de ustedes. Si en control.php se determina que el usuario y contraseña ingresado corresponde al usuario y contraseña que se encuentra en el Active Directory, redirecciona hacia un archivo app.php el cual es nuestra primera página de nuestra aplicación.
5. Veamos el contenido básico del archivo app.php
<?php include("seguridad.php"); ?> <html> <head> <title>Bienvenido al sistema</title> </head> <body> Hola! <?php echo $_SESSION["user"]; ?><br> <br> <a href="salir.php">Salir del sistema</a> </body> </html>
Ésta es la página de bienvenida a nuestra aplicación. Muestra el nombre de usuario logueado y el link para cerrar la sesión. La primera línea hace una inclusión de un archivo seguridad.php el cuál es sumamente importante que se incluya en todas las páginas del sistema que se quiera proteger (que requiera autenticación).
6. Entonces veamos el contenido de seguridad.php
<?php @session_start(); if($_SESSION["autentica"] != "SIP"){ header("Location: index.php"); exit(); } ?>
Aquí validamos si realmente el usuario que quiere acceder a ésta página esta autenticado. Si no lo esta, lo direccionamos a la página index.php. Si esta autenticado, verá la página de bienvenida y su nombre de usuario.
7. Finalmente, en app.php vemos que hay un link hacia un archivo salir.php por lo que veamos el código:
<?php session_start(); session_destroy(); header("Location:index.php"); ?>
Básicamente se destruye la sesión y direccionamos a index.php. Si el usuario desea nuevamente entrar a app.php, no podrá dado que deberá de autenticarse.
Veamos entonces unas capturas de su funcionamiento:
Inicio de sesión:
Usuario o contraseña inválida:
Autenticación correcta y primera página del sistema:
Para las dudas, les dejo adjunto el código fuente de ésta mini aplicación.
Espero que le sirva a alguien. Saludos!
Hola Oscar, muy claro y practico tu codigo, se comprende super bien.
Solo tengo una consulta, como puedo hacer para que el usuario y password sea leido de la sesion de windows y no tener que tipearlo? como capturo esos datos? ya que asi lo envio automaticamente para q se valide con el LDAP.
Gracias de antemano
Gracias!, Referente a tu consulta, realmente es un tema interesante… SSO (single sign-on) creo. La verdad es que me intereso el tema e investigué mucho al respecto pero al final lo dejé porque no sé si es posible hacerlo con php y active directory. Por ejemplo, Sharepoint!; Una vez te logueas en Windows (dominio) y abres el Internet Explorer (solo con ese funcionaba… por lo menos la versión de sharepoint que probé en su momento) y el sharepoint te identifica con tu usuario de dominio. Exactamente lo que tu quieres. Si abrías firefox en ésa misma sesión de windows, te pedía usuario y contraseña (típico de microsoft). Si se puede con ASP.NET, debería de haber algo en php, me dije, pero al final no lo culminé. Si logras hacerlo, te agradecería mucho que me dieras el dato.
Excelete post, es lo que andaba buscando hace varios días… se comprende a la perfección, esta semana lo intentaré implementar con el AD de la empresa.
Muchas gracias por este tipo de artículos, son de mucha utiidad!
Saludos
De nada!, Qué bueno que te sea útil. Saludos!
Inge… recientente estoy desarrollando un sistema de control de usuarios en php, utilizo el patron de desarollo MVC para una tesis, el caso es el siguiente:
los usuarios que se loguean en el sistema tiene asignado un perfil de usuario «administrador, reportes, restriccion», de esta manera hay un tabla menús donde se almacenan un menú dinamico que en base al usuario logueado este se lo muestra, tengo una tabla llamada menu_perfil que es donde se registro el id de perfil y el id de menu, como puedo hacer para que el usuario logueado tenga acceso o no al menu que tengo registrado en esta tabla en base a su perfil y el menú asignado?
espero no haber sido muy confusa mi explicación y me puedan orientar en ello.
Buenos Días
muy buen post, quería preguntar como puedo grabar el usuario y la ip en una tabla de mi base de datos cuando se genere una transacción?
Gracias
Gracias
Me da error , el ejemplo dice que no sabe quién es el método ldap_connect($ds,$puertoldap);
que me sugieren , gracias
Arney instala LDAP, en centos es yum install php-ldap y reinicia el apache!
Buen día
Muy claro la explicación, hizo autenticación perfecta con directorio activo de windows 2008
Muchas gracias
Excelente!!! (Y)
Muy bueno y limpio tu ejemplo, muchas gracias
De nada, un gusto!
hola, muy bien explicado ; tengo una consulta he aplicado todo el codigo en mi proyecto y me resulta bien al probarlo en mi local pero cuando lo subo a un servidor e ingresar los mismos datos me sale el mensaje de usuario o clave incorrecta por favor ayudame con ese problema gracias
buenas tardes, me gustaria saber si es posible al logear un usuario obtener datos del mismo como unidad organizativa sus nombres completos entre otros…
Gracias
si quiero hacer una búsqueda de un grupo de usuarios para darles un determinado de perfil según su grupo como seria.?
Oscar
Gracias por tu código… 🙂 me aclaro varias dudas!!
Gracias hermano. Que buen manual!. Una consulta, ¿Cómo puedo jalar datos del Active Directory de un usuario específico y enviarlos a un formulario HTML? Por favor hermano, Gracias
Gracias De Verdad Tu Post me Sirvio muchisimo!!!! Espero poder Ayudar de la misma manera a los demas en un futuro, cuando adquiera mas conocimientos.
De nada!, excelente, eso sería muy bueno! Si todos compartiéramos los conocimientos creo que estaríamos en un mejor lugar para vivir 🙂
Saludos!
Hola buenos días, se puede que en lugar del usuario te muestre el campo del nombre completo de AD?
Saludos y gracias por tu ejemplo.
Una excelente aportación, me esta haciendo muy útil.
De nada! Bueno te ha servidor. Saludos!
Gracias oscar.
De nada! Saludos!
Hola una pregunta, el usuario y contrasena es de alguien que tiene acceso al directorio activo para poder ver credenciales y eso, o solo para logearse con sus propias credenciales aunque no tenga acceso a verlo?
¡Hola!, no comprendo bien tu pregunta… pero creo poder contestar. El usuario a loguearse debe de ser un usuario de active directory; a qué grupo pertenece, o qué permisos tiene realmente no es relevante, sino que solo se necesita que esté creado en AD como usuario (que esté activo y tenga su clave xD ) para poder autenticarse en éste login. ¡Saludos!
buen día estimado tu código me sirvió un montón ,
Sabras como de esta manera pueda ver todos los usuarios del ad y sus ou .
Buenas tardes,
Tu codigo me sirvio un monton y lo agradezco. necesitaria saber si existe una forma con este mismo codigo, pero de listar todos los usuarios que tengo en el AD, muchas gracias!
Hola Oscar,
Muy claro tu código, Soy nuevo en PHP, apenas unos dias, pero se entiende a la perfección y funciona. Tengo una pregunta, si podrás orientarme. Según el modelo MVC puse los archivos .php en una subcarpeta, me quedó index.php en el root del proyecto y los demás archivos en la carpeta Controllers. No estoy pudiendo volver a index.php. Muy agradecido si me das una manito con eso.
Saludos,
Excelente! Saludoss!!
y si quisiera desbloquear el usuario ad, usando el campo usuario y dni como seria en php?
Profe le agradezco por este aporte tan grande llevaba días buscando como hacer esto, ahora una pregunta como hago para validar que solo deje ingresar si el usuario que se autentica pertenece a determinado grupo de usuarios de el Directorio Activo. gracias
Excelente, me alegro que te sirviera. Pues, referente a la validación que mencionas, pues es de agregar más código al respecto e investigar. Yo recomendaría hacer una tablita llamada digamos «Grupos», de tal manera gestionar la seguridad del sistema a tu gusto; entonces, la validación se hace contra Active Directory y, la seguridad a nivel de grupos en el aplicativo… es como más práctico pienso. Si aún así lo quieres hacer mediante AD, habría que investigar más en el mundo de AD. https://docs.microsoft.com/en-us/windows/desktop/ad/group-objects
Buenas, es muy bueno el post.
Ahora te hago una consulta, es posible hacer que el usuario pueda cambiar su clave?
Si la clave del usuario caduca, se la dejaria cambiar?
hola buenas tardes por favor me podrías ayudar soy nuevo en ldap y necesito un filtro que me autentique un usuario en grupo llamado ti-funcional que debería cambiar, gracias
Hola, muchas gracias por compartir me ha servido mucho, solo tengo una pregunta, que en la bienvenida en lugar de mostrar el username se podrá traer el nombre completo con apellidos
Hola Luis Caicedo, yo tenía la misma pregunta, estoy empezando con PHP y lo resolví del siguiente modo:
1- Copie el código de Ldap.php dentro de Control.php para no tener que invocar a una función.
2- Justo debajo donde dice:
$array = $info[0][«samaccountname»][0];
Agregué este código:
$fields = array(«displayname»);
$sr = @ldap_search($ldapconn, $dn, $filter, $fields);
$info = @ldap_get_entries($ldapconn, $sr);
$nombre = $info[0][«displayname»][0];
3- Finalmente agregué el nombre el usuario al array SESSION:
$_SESSION[«nombre»] = $nombre;
Espero que te sirva.
Saludos,
Hola buenos días, se puede que en lugar del usuario te muestre el campo del nombre completo de AD?
Saludos y gracias por tu ejemplo.
Gracias master me sirvio para la intranet de la empresa
De nada, que bueno!. Saludos