Authentifizierung gegen Active Directory mit Python + LDAP

89

Wie authentifiziere ich mich mit Python + LDAP gegen AD? Ich benutze derzeit die Python-LDAP-Bibliothek und alles, was sie produziert, sind Tränen.

Ich kann nicht einmal binden, um eine einfache Abfrage durchzuführen:

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()

Wenn [email protected] password usernameich dies mit ausführe, habe ich einen von zwei Fehlern:

Invalid Credentials - Wenn ich falsch schreibe oder absichtlich falsche Anmeldeinformationen verwende, kann die Authentifizierung nicht durchgeführt werden.

ldap.INVALID_CREDENTIALS: {'info': '80090308: LdapErr: DSID-0C090334, Kommentar: AcceptSecurityContext-Fehler, Daten 52e, vece', 'desc': 'Ungültige Anmeldeinformationen'}

Oder

ldap.OPERATIONS_ERROR: {'info': '00000000: LdapErr: DSID-0C090627, Kommentar: Um diesen Vorgang auszuführen, muss eine erfolgreiche Bindung für die Verbindung abgeschlossen werden., Daten 0, vece', 'desc': 'Operations error '}

Was verpasse ich, um richtig zu binden?

Ich erhalte die gleichen Fehler auf Fedora und Windows.

1729
quelle
2
"... und alles was es produziert sind Tränen." Hat Tränen Reim mit Bären oder Bier?
Philshem

Antworten:

47

ich habe gefehlt

l.set_option(ldap.OPT_REFERRALS, 0)

Von der Init.

1729
quelle
3
Die Hauptursache für diesen Fehler ist, dass Sie in der ersten Antwort Verweise haben und der Windows-LDAP-Code die Anmeldeinformationen nicht an den Verweisserver sendet. Wenn Sie Kerberos-Anmeldeinformationen verwendet haben, sollte dies funktionieren.
Schlenk
2
Ich hatte verschiedene Symptome, aber dieselbe Option hat mein Problem behoben. Fasst es in einem Blog-Beitrag zusammen: chaverma.com/blog/index.php/2013/06/…
Chris
Ich bin mir nicht sicher, ob ich verwandt bin, aber ich hatte das gleiche Problem und es scheint, dass die Lösung von 1729 etwas bewirkt hat - aber manchmal antwortet der LDAP-Server einfach sofort auf UNGÜLTIGE KREDENTIALIEN. Nach einer Weile beruhigt es sich und funktioniert wieder.
Nitay
28

Wenn Sie für die Verwendung von pywin32 offen sind, können Sie Win32-Aufrufe von Python verwenden. Dies tun wir auf unserem CherryPy-Webserver:

import win32security
token = win32security.LogonUser(
    username,
    domain,
    password,
    win32security.LOGON32_LOGON_NETWORK,
    win32security.LOGON32_PROVIDER_DEFAULT)
authenticated = bool(token)
davidavr
quelle
3
einfach und sauber! Vielen Dank!
Alexroat
Diese Lösung funktionierte für mich in einer Python Flask-Anwendung hinter einem restriktiven NTLM-Unternehmensproxy. Einige andere LDAP-basierte Optionen würden einfach nicht funktionieren.
Gigaflop
7

Das hat bei mir funktioniert. L.set_option (ldap.OPT_REFERRALS, 0) war der Schlüssel für den Zugriff auf das ActiveDirectory. Darüber hinaus denke ich, dass Sie ein "con.unbind ()" hinzufügen sollten, um die Verbindung zu schließen, bevor Sie das Skript beenden.

Alfredocambera
quelle
8
Aus der Python-LDAP-Dokumentation : Instanzen von LDAPObjectwerden von zurückgegeben initialize(). Die Verbindung wird automatisch gelöst und geschlossen, wenn das LDAP-Objekt gelöscht wird.
Søren Løvborg
Sie schließen die Sitzung, nicht die Verbindung.
Romulus
5

Hier ist ein einfacher Code, der für mich funktioniert.

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

Dies basiert auf einer vorherigen Antwort .

JohnMudd
quelle
Dies funktioniert nicht mehr, Sie erhaltenAttributeError: module 'ldap' has no attribute 'open'
Josh Correia
3

Wenn Sie Kerberos installiert haben und mit AD sprechen, wie dies beispielsweise bei Centrify Express der Fall ist und ausgeführt wird, verwenden Sie möglicherweise nur Python-Kerberos. Z.B

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

würde True zurückgeben. Ein Benutzer 'joe' hat das Passwort 'pizza' im Kerberos-Bereich X.PIZZA.COM. (Ich denke, letzteres entspricht normalerweise dem Namen der AD-Domäne.)

Dima Pasechnik
quelle
2

Ich sehe Ihren Kommentar an @Johan Buret über den DN, der Ihr Problem nicht behebt, aber ich glaube auch, dass Sie sich darum kümmern sollten.

In Ihrem Beispiel lautet der DN für das Standardadministratorkonto in AD: cn = Administrator, cn = Benutzer, dc = meine Domäne, dc = co, dc = uk - versuchen Sie das bitte.

Daniel Bungert
quelle
2

Basierend auf dem hervorragenden ldap3-Tutorial :

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

Ich habe das oben genannte in Python3 gemacht, aber es soll mit Python 2 kompatibel sein.

Nagev
quelle
1

Ich habe versucht hinzuzufügen

l.set_option (ldap.OPT_REFERRALS, 0)

aber statt eines Fehlers hängt Python einfach und reagiert auf nichts mehr. Vielleicht baue ich die Suchabfrage falsch. Was ist der Basisteil der Suche? Ich verwende das gleiche wie der DN für die einfache Bindung (oh, und ich musste l.simple_bindstattdessen tun 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)

Ich verwende AD LDS und die Instanz ist für das aktuelle Konto registriert.

Lanoxx
quelle
1

Ich hatte das gleiche Problem, aber es ging um die Passwortkodierung

.encode('iso-8859-1')

Problem gelöst.

Dr.Ü
quelle
0

Verwenden Sie einen eindeutigen Namen, um sich bei Ihrem System anzumelden. "CN=Your user,CN=Users,DC=b2t,DC=local" Es sollte auf jedem LDAP-System einschließlich AD funktionieren

Johan Buret
quelle
0

Für mich hat der Wechsel von simple_bind_s()zu bind()den Trick gemacht.

xcl
quelle