Autenticazione su active directory utilizzando python + ldap


89

Come faccio ad autenticarmi contro AD usando Python + LDAP. Attualmente sto usando la libreria python-ldap e tutto ciò che sta producendo sono le lacrime.

Non riesco nemmeno a eseguire il binding per eseguire una semplice query:

import sys
import ldap


Server = "ldap://my-ldap-server"
DN, Secret, un = sys.argv[1:4]

Base = "dc=mydomain,dc=co,dc=uk"
Scope = ldap.SCOPE_SUBTREE
Filter = "(&(objectClass=user)(sAMAccountName="+un+"))"
Attrs = ["displayName"]

l = ldap.initialize(Server)
l.protocol_version = 3
print l.simple_bind_s(DN, Secret)

r = l.search(Base, Scope, Filter, Attrs)
Type,user = l.result(r,60)
Name,Attrs = user[0]
if hasattr(Attrs, 'has_key') and Attrs.has_key('displayName'):
  displayName = Attrs['displayName'][0]
  print displayName

sys.exit()

Eseguire questo con myusername@mydomain.co.uk password usernamemi dà uno dei due errori:

Invalid Credentials - Quando digito erroneamente o utilizzo intenzionalmente credenziali errate, l'autenticazione non viene eseguita.

ldap.INVALID_CREDENTIALS: {'info': '80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 52e, vece', 'desc': 'Invalid credentials'}

O

ldap.OPERATIONS_ERROR: {'info': '00000000: LdapErr: DSID-0C090627, comment: Per eseguire questa operazione è necessario completare con successo un bind sulla connessione., data 0, vece', 'desc': 'Operazioni di errore '}

Cosa mi sto perdendo per legare correttamente?

Ricevo gli stessi errori su Fedora e Windows.


2
"... e tutto ciò che produce sono lacrime." Tears fa rima con Bears o Beers?
philshem

Risposte:


47

Mi mancava

l.set_option(ldap.OPT_REFERRALS, 0)

Dall'init.


3
La causa principale di questo bug è che hai dei riferimenti nella risposta iniziale e il codice LDAP di Windows non invia le credenziali al server di riferimento. Se hai usato le credenziali Kerberos dovrebbe funzionare.
schlenk

2
Avevo sintomi diversi ma questa stessa opzione ha risolto il mio problema. Riassumendolo in un post sul blog: chaverma.com/blog/index.php/2013/06/…
Chris

Non sono sicuro se correlato, ma ho avuto lo stesso problema e sembra che la soluzione del 1729 abbia fatto qualcosa - Ma a volte il server LDAP risponde immediatamente alle CREDENZIALI NON VALIDE. Dopo un po 'si calma e riprende a funzionare.
Nitay

28

Se sei aperto a usare pywin32, puoi usare le chiamate Win32 da Python. Questo è ciò che facciamo nel nostro server web CherryPy:

import win32security
token = win32security.LogonUser(
    username,
    domain,
    password,
    win32security.LOGON32_LOGON_NETWORK,
    win32security.LOGON32_PROVIDER_DEFAULT)
authenticated = bool(token)

3
semplice e pulito! Grazie!
alexroat

Questa soluzione ha funzionato per me in un'applicazione Python Flask mentre era dietro un proxy aziendale NTLM restrittivo. Alcune altre opzioni basate su LDAP semplicemente non funzionerebbero.
Gigaflop

7

Per me ha funzionato, l.set_option (ldap.OPT_REFERRALS, 0) è stata la chiave per accedere ad ActiveDirectory. Inoltre, penso che dovresti aggiungere un "con.unbind ()" per chiudere la connessione prima di terminare lo script.


8
Dalla documentazione di python-ldap : Le istanze di LDAPObjectvengono restituite da initialize(). La connessione viene automaticamente scollegata e chiusa quando l'oggetto LDAP viene eliminato.
Søren Løvborg

Chiudi la sessione, non la connessione.
Romolo

5

Ecco un semplice codice che funziona per me.

import ldap  # run 'pip install python-ldap' to install ldap module.
conn = ldap.open("ldaphost.company.com")
conn.simple_bind_s("myuser@company.com", "mypassword")

Questo si basa su una risposta precedente .


1
Non funziona più, riceveraiAttributeError: module 'ldap' has no attribute 'open'
Josh Correia

3

se hai Kerberos installato e stai parlando con AD, come sarebbe il caso, ad esempio, di Centrify Express installato e in esecuzione, potresti semplicemente usare python-kerberos. Per esempio

import kerberos
kerberos.checkPassword('joe','pizza','krbtgt/x.pizza.com','X.PIZZA.COM')`

restituirebbe True se un utente "joe" ha la password "pizza" nel regno di Kerberos X.PIZZA.COM. (in genere, penso, quest'ultimo sarebbe lo stesso del nome del dominio AD)


2

Vedo il tuo commento a @Johan Buret sul fatto che DN non risolve il tuo problema, ma credo anche che sia quello che dovresti esaminare.

Dato il tuo esempio, il DN per l'account amministratore predefinito in AD sarà: cn = Administrator, cn = Users, dc = mydomain, dc = co, dc = uk - provalo.


2

Basato sull'eccellente tutorial di ldap3 :

>>> from ldap3 import Server, Connection, ALL, NTLM
>>> server = Server('server_name_or_ip', get_info=ALL)
>>> conn = Connection(server, user="user_name", password="password", auto_bind=True)
>>> conn.extend.standard.who_am_i()
>>> server.info

Ho fatto quanto sopra in Python3 ma dovrebbe essere compatibile con Python 2.


1

Ho provato ad aggiungere

l.set_option (ldap.OPT_REFERRALS, 0)

ma invece di un errore Python si blocca e non risponderà più a nulla. Forse sto costruendo la query di ricerca in modo errato, qual è la parte Base della ricerca? Sto usando lo stesso del DN per il binding semplice (oh, e dovevo fare l.simple_bind, invece di l.simple_bind_s):

import ldap
local = ldap.initialize("ldap://127.0.0.1")
local.simple_bind("CN=staff,DC=mydomain,DC=com")
#my pc is not actually connected to this domain 
result_id = local.search("CN=staff,DC=mydomain,DC=com", ldap.SCOPE_SUBTREE, "cn=foobar", None)
local.set_option(ldap.OPT_REFERRALS, 0)
result_type, result_data = local.result(result_id, 0)

Sto usando AD LDS e l'istanza è registrata per l'account corrente.


1

Ho avuto lo stesso problema, ma riguardava la codifica della password

.encode('iso-8859-1')

Problema risolto.


0

Utilizzare un nome distinto per accedere al sistema. "CN=Your user,CN=Users,DC=b2t,DC=local" Dovrebbe funzionare su qualsiasi sistema LDAP, incluso AD


0

Per me il passaggio da simple_bind_s()a bind()ha funzionato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.