Uwierzytelnianie w PHP przy użyciu LDAP przez Active Directory

104

Szukam sposobu na uwierzytelnianie użytkowników przez LDAP z PHP (z usługą Active Directory jako dostawcą). Najlepiej byłoby, gdyby mógł działać w IIS 7 ( adLDAP robi to na Apache). Czy ktoś zrobił coś podobnego i odniósł sukces?

  • Edycja: wolałbym bibliotekę / klasę z kodem, który jest gotowy do użycia ... Byłoby głupio wymyślać koło, gdy ktoś już to zrobił.
DV.
źródło
Myślę, że drupal ma moduł na to
redben

Odpowiedzi:

167

Importowanie całej biblioteki wydaje się nieefektywne, gdy wszystko, czego potrzebujesz, to zasadniczo dwa wiersze kodu ...

$ldap = ldap_connect("ldap.example.com");
if ($bind = ldap_bind($ldap, $_POST['username'], $_POST['password'])) {
  // log them in!
} else {
  // error message
}
ceejayoz
źródło
43
Niektóre instalacje AD powiążą się pomyślnie, jeśli podane hasło jest puste. Uważaj na to! Może być konieczne ustawienie niepustego hasła przed próbą uwierzytelnienia.
diolemo
@diolemo Czy istnieje sposób, aby temu zapobiec bez sprawdzania, czy hasło jest puste?
Naftali aka Neal
@Neal Możesz użyć, ldap_set_optionaby zachowywać się w inny sposób. Może ustawienie wersji protokołu? Będziesz musiał eksperymentować. Osobiście sugerowałbym sprawdzenie, czy nie ma pustego hasła, tak dla bezpieczeństwa.
diolemo
@diolemo Zrobiłem nowe pytanie związane z tym.
Naftali aka Neal
Do anonimowego redaktora: nie, według mojej wiedzy oczyszczanie danych wejściowych nie jest tutaj wymagane, ponieważ ldap_bindbyłoby to obsługiwane, a znaki specjalne nie są problemem.
ceejayoz
14

Można by pomyśleć, że zwykłe uwierzytelnienie użytkownika w Active Directory byłoby dość prostym procesem przy użyciu LDAP w PHP bez potrzeby korzystania z biblioteki. Ale jest wiele rzeczy, które mogą to dość szybko skomplikować:

  • Musisz zweryfikować dane wejściowe. W przeciwnym razie zostanie przesłana pusta nazwa użytkownika / hasło.
  • Powinieneś upewnić się, że nazwa użytkownika / hasło są poprawnie zakodowane podczas wiązania.
  • Powinieneś szyfrować połączenie za pomocą TLS.
  • Używanie oddzielnych serwerów LDAP w celu zapewnienia nadmiarowości w przypadku awarii jednego z nich.
  • Otrzymywanie informacyjnego komunikatu o błędzie, jeśli uwierzytelnianie nie powiedzie się.

W większości przypadków łatwiej jest skorzystać z biblioteki LDAP obsługującej powyższe. Ostatecznie skończyło się na utworzeniu własnej biblioteki, która obsługuje wszystkie powyższe punkty: LdapTools (Cóż, nie tylko do uwierzytelniania, może zrobić znacznie więcej). Można go używać w następujący sposób:

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...
}

Powyższe wywołanie uwierzytelniające:

  • Sprawdź, czy nazwa użytkownika ani hasło nie są puste.
  • Upewnij się, że nazwa użytkownika / hasło są poprawnie zakodowane (domyślnie UTF-8)
  • Wypróbuj alternatywny serwer LDAP na wypadek awarii jednego z nich.
  • Zaszyfruj żądanie uwierzytelnienia za pomocą TLS.
  • Podaj dodatkowe informacje, jeśli się nie powiedzie (np. Zablokowane / wyłączone konto itp.)

Istnieją inne biblioteki, które również to robią (takie jak Adldap2). Czułem się jednak na tyle zmuszony, aby podać dodatkowe informacje, ponieważ najbardziej głosowana odpowiedź jest w rzeczywistości zagrożeniem bezpieczeństwa, na którym można polegać, bez przeprowadzania weryfikacji danych wejściowych i bez korzystania z TLS.

ChadSikorra
źródło
1
W przypadku połączeń LDAP protokół TLS został wycofany i zastąpiony przez StartTLS: openldap.org/faq/data/cache/605.html .
zenlord
2
@zenlord Używanie ldaps://formatu połączenia jest przestarzałe. W moim przykładzie, gdy określisz, setUseTls(true)że używa ldap://formatu, a następnie wydaje StartTLS przy użyciu ldap_start_tls($connection). Tak więc sam protokół TLS nie został wycofany, po prostu łączy się za pomocą ldaps://(co w rzeczywistości łączy się z LDAP przez zupełnie inny port).
ChadSikorra
12

Robię to po prostu przekazując poświadczenia użytkownika do ldap_bind ().

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

Jeśli konto można powiązać z LDAP, jest prawidłowe; jeśli nie może, nie jest. Jeśli wszystko, co robisz, to uwierzytelnianie (nie zarządzanie kontem), nie widzę potrzeby posiadania biblioteki.

Scott Reynen
źródło
9

Podoba mi się klasa Zend_Ldap , możesz używać tylko tej klasy w swoim projekcie, bez Zend Framework.

CMS
źródło
1
Zadałem sobie trud wdrożenia powyższego, aby stwierdzić, że dotyczy to zarządzania brakiem uwierzytelnienia. Zamierzam przejść na zend.auth.adapter.ldap
vdidxho