[RESOLU] PHP active directory

Eléphant du PHP | 385 Messages

20 oct. 2016, 09:23

Bonjour à tous, Pourriez vous m'aider?

Je souhaiterais faire un système ou la personne se logue avec l'active directory, ici la personne est déjà sur l'active directory je veux juste récupérer ces informations pour donner des droits sur l'application selon son nom.

Merci à vous

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

20 oct. 2016, 09:31

salut

utilise l'extension ldap de php

@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 385 Messages

20 oct. 2016, 12:00

Merci de votre réponse, si je veux une connexion automatique active directory est une bonne idée? je peux sinon passer par le nom de la personne sur windows? sinon j'utiliserais des cookies quel est la meilleurs solution pour simplifier la vie aux utilisateurs?

Merci à vous.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

20 oct. 2016, 14:59

salut,

c'est une appli web tu ne peux pas obtenir le nom de l'utilisateur connecter comme ça (tu veux pas le mot de passe de session, l'accès aux disques et a son compte en banque en plus ;) ).
Tu peux essayer de faire un sso, comme par exemple kerberos, après cela dépends du besoin et du contexte.
Est ce que c'est une application utilisée très souvent, ou pas du tout.
Est ce que l'application à un besoin de sécurité extra ordinaire (pour générer le menu de la cantine on se fou d'un vol de session, pour gérer un parc de missiles c'est pas la même chose :) ).

tu peux utiliser les cookiex ou autre chose (localstorage ..).
regarde du cote de l'authentification avec jwt (http://jwt.io) tu a moyen de faire un sso avec cela.

tu peux imaginer avoir un serveur centrale qui garde les ip des machines et le token utilisateur ce qui te permet de savoir qui est connecté et cela de façon transparente pour l'utilisateur.
cela nécessite
- que la connexion d'un poste mette a jour la correspondance ip / utilisateur
- que les ip soit relativmement fixe (bail ip permanent sans pour autant être fixe).
mais bon c'est faible coté sécurité, l’usurpation est simple à réaliser.

par contre si tu as plusieurs application accessible depuis une autre (un portail ...) alors la le sso prend tout son sens, l'utilisateur se connecte sur le portail, tu place un cookie avec les infos que tu as besoins pour l'auto authentification, et les autres application (du même domaine / sous domaine) auront accès au cookie et pourront auto authentifier la personne.

dans le cas d'application monolithique c'est aussi simple de mettre en place un formulaire de connexion qui tape sur l'ad.
il existe aussi des solutions applicative (comme le sso d'oracle) qui permet de remplir automatiquement les champs de formulaire de connexion et de la valider quand on arrive.

@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 385 Messages

21 oct. 2016, 10:49

Merci, le sso est-il du ntlm? j'ai trouvé ce code

Code : Tout sélectionner

<?php // loune 25/3/2006, updated 22/08/2009 // For more information see: // http://siphon9.net/loune/2007/10/simple-lightweight-ntlm-in-php/ // // This script is obsolete, you should see // http://siphon9.net/loune/2009/09/ntlm-authentication-in-php-now-with-ntlmv2-hash-checking/ // // NTLM specs http://davenport.sourceforge.net/ntlm.html $headers = apache_request_headers(); if (!isset($headers['Authorization'])){ header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: NTLM'); exit; } $auth = $headers['Authorization']; if (substr($auth,0,5) == 'NTLM ') { $msg = base64_decode(substr($auth, 5)); if (substr($msg, 0, 8) != "NTLMSSP\x00") die('error header not recognised'); if ($msg[8] == "\x01") { $msg2 = "NTLMSSP\x00\x02\x00\x00\x00". "\x00\x00\x00\x00". // target name len/alloc "\x00\x00\x00\x00". // target name offset "\x01\x02\x81\x00". // flags "\x00\x00\x00\x00\x00\x00\x00\x00". // challenge "\x00\x00\x00\x00\x00\x00\x00\x00". // context "\x00\x00\x00\x00\x00\x00\x00\x00"; // target info len/alloc/offset header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: NTLM '.trim(base64_encode($msg2))); exit; } else if ($msg[8] == "\x03") { function get_msg_str($msg, $start, $unicode = true) { $len = (ord($msg[$start+1]) * 256) + ord($msg[$start]); $off = (ord($msg[$start+5]) * 256) + ord($msg[$start+4]); if ($unicode) return str_replace("\0", '', substr($msg, $off, $len)); else return substr($msg, $off, $len); } $user = get_msg_str($msg, 36); $domain = get_msg_str($msg, 28); $workstation = get_msg_str($msg, 44); print "You are $user from $domain/$workstation"; } } ?>
quand je tente de le tester sous wamp j'ai site innaccessible ou ERR_UNEXPECTED.. Comment puis-je procéder?

Merci à vous.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

21 oct. 2016, 10:56

alors sso => https://fr.wikipedia.org/wiki/Authentification_unique
on doit pouvoir dire que ntml est une sorte de sso microsoft.

ntlm c'est microsoft, si c'est limité à un parc d'entreprise qui ne contient que des machine windows c'est utilisable.

ensuite ton script indique qu'il est obsolète a tu tester la version ntmlv2 ?

reste a savoir qui va fournir l'entête Authorization, parce que bon le gars qui arrive sur ton appli il ne l'a pas forcément.

pense à regarder les commentaires de la seconde version il y a des choses qui pourrait t'aider.
@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 385 Messages

21 oct. 2016, 12:22

En effet je viens de regarder

Code : Tout sélectionner

include('ntlm.php'); function get_ntlm_user_hash($user) { $userdb = array('loune'=>'test', 'you'=>'gg', 'a'=> 'a'); if (!isset($userdb[strtolower($user)])) return false; return mhash(MHASH_MD4, ntlm_utf8_to_utf16le($userdb[strtolower($user)])); } session_start(); $auth = ntlm_prompt("testwebsite", "testdomain", "mycomputer", "testdomain.local", "mycomputer.local", "get_ntlm_user_hash"); if ($auth['authenticated']) { print "You are authenticated as $auth[username] from $auth[domain]/$auth[workstation]"; }
mais ici aussi il faut avoir le nom d'utilisateur pour permettre la connexion, finalement autant passer par un formulaire avec cookie je pense.

Merci à vous pour votre aide.

Eléphant du PHP | 385 Messages

17 nov. 2016, 10:53

Bonjour Je réouvre le sujet,

En effet les utilisateurs veulent absolument cette fonctionnalité :(
Voilà ce que j'ai trouvé de mon côté pour loger automatiquement :

Code : Tout sélectionner

header('WWW-Authenticate: Basic realm="this realm"'); header("HTTP/1.0 401 Unauthorized"); session_start(); $user = $_SERVER['PHP_AUTH_USER']; echo $user;
Seul problème je ne peux tester qu'avec wamp et la variable

Code : Tout sélectionner

$_SERVER['PHP_AUTH_USER']
n'ai pas reconnu par contre avec le header j'ai une fenêtre pour se logger qui apparaît.
Mais je ne comprend pas trop comment procéder par exemple pour les droits, quel est la différence entre ntlm et une authentification par active directory? voici mon script actuel sans AD

Code : Tout sélectionner

<?php session_start(); include('Connexion/connexion.php'); $_SESSION['ERREUR'] = ""; //verification session if (isset($_SESSION['id_personne'])) { $id_personne = $_COOKIE['id_personne']; // Remplace les simple quote par des double quote pour éviter les problemes d'injection sql setcookie('id_personne', $id_personne, time() + 365*24*3600, "/"); $_SESSION['id_personne'] = $id_personne; header('Location: accueil.php'); // redirige vers l'accueil } //verification cookie if (isset($_COOKIE['id_personne']) || !empty($_COOKIE['id_personne'])) { $id_personne = $_COOKIE['id_personne']; // Remplace les simple quote par des double quote pour éviter les problemes d'injection sql setcookie('id_personne', $id_personne, time() + 365*24*3600, "/"); $_SESSION['id_personne'] = $id_personne; header('Location: accueil.php'); // redirige vers l'accueil } //verification formulaire login if ((!empty($_POST['login']) && !empty($_POST['mdp']))) { // Test si les champs sont plein $login = $_POST['login']; // Remplace les simple quote par des double quote pour éviter les problemes d'injection sql $mdp = sha1($_POST['mdp']); // Vérification des identifiants $req = $bdd->prepare('SELECT id_personne FROM personne WHERE login = :login AND mdp_personne = :mdp'); $req->execute(array( 'login' => $login, 'mdp' => $mdp)); $resultat = $req->fetch(PDO::FETCH_ASSOC); if (!$resultat) { $_SESSION['ERREUR'] = "Login et/ou mot de passe incorrect"; // Message d'erreur } else { setcookie('id_personne', $resultat['id_personne'], time() + 365*24*3600, "/"); $_SESSION['id_personne'] = $resultat['id_personne']; header('Location: accueil.php'); // redirige vers l'accueil } } ?> <!DOCTYPE html> <html> <head> <title>Login</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" > <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" > <link rel="stylesheet" href="css/formulaire.css" > <link rel="stylesheet" href="css/general.css" > </head> <script src="js/jquery.min.js"></script> <script src="bootstrap/js/bootstrap.min.js"></script> <body> <body class="couleur3"> <!-- header --> <?php if(!empty($_SESSION['ERREUR'])) { echo ' <div class="alert alert-warning message" style="font-size:20px;"> <a href="#" class="close" data-dismiss="alert">&times;</a> '.$_SESSION['ERREUR'].' </div>'; session_destroy(); } ?> <form id="form_connexion" class="form-login" method='post' action="#" > <fieldset class="col-md-3 col-md-offset-4 login"> <form action="#" id="info" method="post"> <div class="form-group"> <label for="login-text" class="form-control-label">login:</label> <input type="text" class="form-control" name="login" id="login" required> </div> <div class="form-group"> <label for="mdp-name" class="form-control-label">mot de passe:</label> <input type="password" class="form-control" name="mdp" id="mdp" required> </div> <button type="submit" name="submit" class="btn btn-success col-md-offset-2 button-log">Connexion</button> </form> </fieldset> </body> </body> </html>
Merci d'avance pour votre aide.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

17 nov. 2016, 11:54

salut,

les deux premier if font la même chose
pire les deux conditions du second sont quasi identiques le empty test l’existence ou non de la variable (si ce n'était pas le cas tu aurais une erreur avec ton "ou") de plus fonctionnellement ce que tu veux faire c'est la même chose.
au finale if(!empty($_COOKIE['id_personne']))

attention a ce que le register globals ne soit pas a on si tu as un beau cas d'écrasement de variable possible en utilisant partout "id_personne"

la vérification du formulaire devrait être dans un else if du 1er if (est qu'il y a le cookie ? oui je l'utilise sinon je regarde si formulaire posté sinon formulaire de connexion)


au passage le mot de passe en clair dans le base c'est quelque chose qui ne doit pas exister ;)

Pour le reste, en règle générale il y "quelque chose" qui permet de savoir si l'utilisateur est déjà sur le réseau.


Par exemple il existe Oauth
soit ton serveur http peux le faire soit un serveur tiers te donnes l'info (par exemple à partir de l'ip de connexion).

Je ne suis pas un spécialiste du sujet l'ayant éviter le plus possible (sécurité tous ça ;) )

Il existe une solution logicielle d'Oracle qui permette remplir et valider automatiquement les formulaires de connexion des applications.
en gros l'utilisateur se connecte le soft (de mémoire il s'appel sso ;) ) garde les infos de connexion, dès qu'il rencontre un formulaire (qu'il connait ?) il le remplis et le valide, du coup c'est relativement transparent pour l'utilisateur.

ceci dit le sso c'est quand même une faille de sécurité (par exemple un utilisateur quitte son bureau sans verrouiller sa station et c'est open bar pour le mec qui passe derrière, et pas que pour inviter les autres au café / croissant ;) ).

pour ntml : https://fr.wikipedia.org/wiki/NT_Lan_Manager , c'est 'automatique')
il y a des gens qui ont essayé : (serveur windows)
http://stackoverflow.com/questions/3007 ... ost-in-php
a priori il existe un mod_auth_ntml

La connexion avec l'AD il te faut user / passwd et demander à l'AD si c'est bon. tu lui demandes en même temps les groupes auxquels il appartient et avec ça tu sais s'il peux non utiliser ton application et telle ou telle foncitonnalité (sous groupe etc).
Cela nécessite une gestion correcte des groupes dans l'AD.

@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 385 Messages

17 nov. 2016, 13:08

Super merci Mooglie,

Code : Tout sélectionner

<?php session_start(); include('Connexion/connexion.php'); $_SESSION['ERREUR'] = ""; //verification cookie if (!empty($_COOKIE['id_personne'])) { $id_personne = $_COOKIE['id_personne']; // Remplace les simple quote par des double quote pour éviter les problemes d'injection sql setcookie('id_personne', $id_personne, time() + 365*24*3600, "/"); $_SESSION['id_personne'] = $id_personne; header('Location: accueil.php'); // redirige vers l'accueil } else if ((!empty($_POST['login']) && !empty($_POST['mdp']))) { $login = $_POST['login']; // Remplace les simple quote par des double quote pour éviter les problemes d'injection sql $mdp = sha1($_POST['mdp']); // Vérification des identifiants $req = $bdd->prepare('SELECT id_personne FROM personne WHERE login = :login AND mdp_personne = :mdp'); $req->execute(array( 'login' => $login, 'mdp' => $mdp)); $resultat = $req->fetch(PDO::FETCH_ASSOC); if (!$resultat) { $_SESSION['ERREUR'] = "Login et/ou mot de passe incorrect"; // Message d'erreur } else { setcookie('id_personne', $resultat['id_personne'], time() + 365*24*3600, "/"); $_SESSION['id_personne'] = $resultat['id_personne']; header('Location: accueil.php'); // redirige vers l'accueil } } ?> <!DOCTYPE html> <html> <head> <title>Login</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" > <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" > <link rel="stylesheet" href="css/formulaire.css" > <link rel="stylesheet" href="css/general.css" > </head> <script src="js/jquery.min.js"></script> <script src="bootstrap/js/bootstrap.min.js"></script> <body> <body class="couleur3"> <!-- header --> <?php if(!empty($_SESSION['ERREUR'])) { echo ' <div class="alert alert-warning message" style="font-size:20px;"> <a href="#" class="close" data-dismiss="alert">&times;</a> '.$_SESSION['ERREUR'].' </div>'; session_destroy(); } ?> <form id="form_connexion" class="form-login" method='post' action="#" > <fieldset class="col-md-3 col-md-offset-4 login"> <form action="#" id="info" method="post"> <div class="form-group"> <label for="login-text" class="form-control-label">login:</label> <input type="text" class="form-control" name="login" id="login" required> </div> <div class="form-group"> <label for="mdp-name" class="form-control-label">mot de passe:</label> <input type="password" class="form-control" name="mdp" id="mdp" required> </div> <button type="submit" id="submit" name="submit" class="btn btn-success col-md-offset-2 button-log">Connexion</button> </form> </fieldset> </body> </body> </html>
J'ai modifié en conséquence c'est plus à ton gout?
Quand tu dis que mon mot de passe est en clair tu veux dire que le sha1 n'ai pas assez sécurisé?

Code : Tout sélectionner

$mdp = sha1($_POST['mdp']);
Pour le ldap le mot de passe et identifiant, par exemple si je m'est le mien je peux récupérer tout les utilisateurs? pour gérer les droits utilisateurs je dois tout de même avoir une table en parallèle??

Eléphant du PHP | 176 Messages

17 nov. 2016, 13:16

Bonjour,

Le sha1 est effectivement plus assez sécurisé
c'est d'ailleurs pour cela que tous les navigateurs webs (en tout cas Chrome - Firefox - Edge) ne reconnaîtront plus les certificats SSL sha1 comme valide au premier Janvier 2017.
Cordialement
Naroth

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

17 nov. 2016, 13:33

pour le ldap cela dépends de tes droits, généralement c'est un utilisateur technique qui permet de lister les droits des utilisateurs (et de faire toute la tambouille de connexion en fait ;) ).

pour tout ce qui est hash il existe des "raimbow table" du coup ça sert que moyen.
Après tu peux y ajouter un grain de sel.
La solution actuelle fournit par php se base sur blowfish http://php.net/manual/fr/function.password-hash.php

@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 385 Messages

17 nov. 2016, 15:49

Mon script final :D

Code : Tout sélectionner

<?php session_start(); include('Connexion/connexion.php'); $_SESSION['ERREUR'] = ""; //verification cookie if(!empty($_SERVER['REMOTE_USER'])) { include_once('Connexion/ldap_connexion.php'); session_start(); $ldapConn = ldap_connect($ldapServer ) or $this->msg = "ERROR CONNECT LDAP"; $userName = explode("\\", $_SERVER['REMOTE_USER']); $query = "sAMAccountName=".$userName[1]; ldap_set_option($ldapConn,LDAP_OPT_PROTOCOL_VERSION,3); ldap_set_option($ldapConn,LDAP_OPT_REFERRALS,0); $ldapBind = ldap_bind($ldapConn,$rdn,$mdp); $ldapResult = ldap_search($ldapConn,$baseDN,$query); $info = ldap_get_entries($ldapConn,$ldapResult); $currentUserInformation = array(); for ($i=0; $i < $info ["count"]; $i++) { $mail = $info[$i]["mail"][0]; } ldap_unbind($ldapConn); // Vérification des identifiants $req = $bdd->prepare('SELECT id_personne FROM personne WHERE mail = :mail'); $req->execute(array( 'mail' => $mail)); $resultat = $req->fetch(PDO::FETCH_ASSOC); if ($resultat) { setcookie('id_personne', $resultat['id_personne'], time() + 365*24*3600, "/"); $_SESSION['id_personne'] = $resultat['id_personne']; header('Location: accueil.php'); // redirige vers l'accueil } } else if (!empty($_COOKIE['id_personne'])) { $id_personne = $_COOKIE['id_personne']; // Remplace les simple quote par des double quote pour éviter les problemes d'injection sql setcookie('id_personne', $id_personne, time() + 365*24*3600, "/"); $_SESSION['id_personne'] = $id_personne; header('Location: accueil.php'); // redirige vers l'accueil } else if ((!empty($_POST['login']) && !empty($_POST['mdp']))) { $login = $_POST['login']; // Remplace les simple quote par des double quote pour éviter les problemes d'injection sql $mdp = sha1($_POST['mdp']); // Vérification des identifiants $req = $bdd->prepare('SELECT id_personne FROM personne WHERE login = :login AND mdp_personne = :mdp'); $req->execute(array( 'login' => $login, 'mdp' => $mdp)); $resultat = $req->fetch(PDO::FETCH_ASSOC); if (!$resultat) { $_SESSION['ERREUR'] = "Login et/ou mot de passe incorrect"; // Message d'erreur } else { setcookie('id_personne', $resultat['id_personne'], time() + 365*24*3600, "/"); $_SESSION['id_personne'] = $resultat['id_personne']; header('Location: accueil.php'); // redirige vers l'accueil } } ?> <!DOCTYPE html> <html> <head> <title>Login</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" > <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" > <link rel="stylesheet" href="css/formulaire.css" > <link rel="stylesheet" href="css/general.css" > </head> <script src="js/jquery.min.js"></script> <script src="bootstrap/js/bootstrap.min.js"></script> <body> <body class="couleur3"> <!-- header --> <?php if(!empty($_SESSION['ERREUR'])) { echo ' <div class="alert alert-warning message" style="font-size:20px;"> <a href="#" class="close" data-dismiss="alert">&times;</a> '.$_SESSION['ERREUR'].' </div>'; session_destroy(); } ?> <form id="form_connexion" class="form-login" method='post' action="#" > <fieldset class="col-md-3 col-md-offset-4 login"> <form action="#" id="info" method="post"> <div class="form-group"> <label for="login-text" class="form-control-label">login:</label> <input type="text" class="form-control" name="login" id="login" required> </div> <div class="form-group"> <label for="mdp-name" class="form-control-label">mot de passe:</label> <input type="password" class="form-control" name="mdp" id="mdp" required> </div> <button type="submit" id="submit" name="submit" class="btn btn-success col-md-offset-2 button-log">Connexion</button> </form> </fieldset> </body> </body> </html>