Flask mit LDAP3

Django, Flask, Bottle, WSGI, CGI…
Antworten
rbaert
User
Beiträge: 20
Registriert: Mittwoch 5. September 2018, 15:37

Hallo liebe Profis

Ich muss mich an euch wenden, da ich mit meinem Latein leider am Ende bin. Ich versuche ein Web-Dashboard einzurichten, dass für jeden Mitarbeiter personalisierte Ansichten anzeigen soll.

Da die Anzeigen personalisiert sind, ist eine Anmeldung via LDAP erforderlich. Im Moment befinde ich mich in der Phase, wo ich diverse Tests mache und einige Tutorials durchgehe, also noch nichts aussergewöhnliches versuche. Leider scheitere ich bereits beim LDAP Login...

Ich habe mir das Script von https://flask-ldap3-login.readthedocs.i ... start.html eins zu eins kopiert und versucht dies mit meinem LDAP zu verbinden.

Die Settings die ich mitgebe sind:

Code: Alles auswählen

    LDAP_HOST = 'meineFirma.biz'
    LDAP_PORT = xxx
    LDAP_BASE_DN = 'dc=meineFirma,dc=biz'
    LDAP_USER_DN = 'ou=Benutzer,dc=meineFirma,dc=biz'
    LDAP_GROUP_DN = 'ou=Gruppen,dc=meineFirma,dc=biz'
    LDAP_USER_RDN_ATTR = 'cn'
    LDAP_USER_LOGIN_ATTR = 'sAMAccountName'
    LDAP_BIND_USER_DN = 'cn=meinUser,dc=meineFirma,dc=biz'
    LDAP_BIND_USER_PASSWORD = 'meinPasswort'
Dazu muss ich sagen, dass diese Angaben (Host, meinUser, Port und Passwort) von einer anderen Anwendung (Intranet, Plone) stammen, die ebenfalls für's Login Zugriff aufs LDAP braucht. Daher gehe ich davon aus, dass die Angaben stimmen und funktionieren würden.

Was muss ich noch sagen? Ah ja, der DC läuft mit Windows 2012 R2...

Leider gibt mir die Anwendung immer Invalide Username/Passwort zurück. Daher ist wohl irgend eine Einstellung falsch. Ansonsten wird (auch in der Konsole) kein Fehler zurückgegeben ausser:

Code: Alles auswählen

127.0.0.1 - - [31/Oct/2020 23:07:59] "POST /login HTTP/1.1" 200 -
INFO:werkzeug:127.0.0.1 - - [31/Oct/2020 23:07:59] "POST /login HTTP/1.1" 200 -
Lange Rede, kurzer Sinn:
Wie kann ich die Verbindung testen. Ich möchte nun eine kleine Konsolenapp schreiben, mit deren Hilfe ich verschiedene Einstellungen testen könnte. Erstmal muss ich ja wissen, dass die Verbindung zum LDAP funktioniert. Danach, ob ich einen User unter der angegebenen Adresse finde, usw..
Leider reichten meine Python-Kenntnisse (noch) nicht aus, um selber auf eine Lösung zu kommen...

Danke schon im Voraus für eure Hilfe...
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Wie sieht denn der entsprechende Code aus? Du hast ja oben nur Konstanten definiert, aber wie werden diese dann verwendet?

Für LDAP-Anbindungen gibt es python-ldap, evtl. baut flask hier sogar drauf auf und du könntest die Verbindung so vorab testen, ohne den Umweg über die flask_ldap-Konfiguration um Fehler bei der Verwendung des Frameworks auszuschließen.

Unter linux gibt es auch noch ldapsearch, für Windows Softerra.
When we say computer, we mean the electronic computer.
einfachTobi
User
Beiträge: 491
Registriert: Mittwoch 13. November 2019, 08:38

Ich habe vor kurzem eine Anbindung mit fflask_ldap3_login realisiert.
Hier die entsprechende Verwendung:

Code: Alles auswählen

from flask_ldap3_login import AuthenticationResponseStatus, LDAP3LoginManager

app.config["LDAP_HOST"] = "<ip>"
app.config["LDAP_BASE_DN"] = "OU=Benutzer,OU=FIRMA_FOO,DC=intra,DC=FIRMA_BAR,DC=de"
app.config["LDAP_USER_SEARCH_SCOPE"] = "SUBTREE"
app.config["LDAP_USER_LOGIN_ATTR"] = "sAMAccountName"
app.config["LDAP_BIND_USER_DN"] = r"ACCOUNTNAME"
app.config["LDAP_BIND_USER_PASSWORD"] = "PASSWORD_DES_BIND_USERS"
ldap = LDAP3LoginManager(app)

auth = ldap.authenticate(username, password)
        if password and auth.status == AuthenticationResponseStatus.success:
            print("Eingeloggt!")
Der BASE_DN ist natürlich, so wie der Rest auch, anzupassen. Vielleicht kannst du mit dem AD Explorer ja erstmal schauen, ob du überhaupt einen korrekten Pfad angegeben hast.
rbaert
User
Beiträge: 20
Registriert: Mittwoch 5. September 2018, 15:37

Hallo zusammen

Danke für die Antworten. Leider bin ich noch trotzdem nicht wirklich weiter gekommen. Mit dem Active Directory Explorer habe ich die Verbindung geprüft. Diese funktioniert einwandfrei.

Ich habe mich nun in die LDAP3 Doku vertieft und einige Tests durchgeführt. Leider bin ich wohl zu doof dafür oder ich habe etwas an der Funktionsweise von LDAP3 nicht verstanden...

Zum Code:
Wenn ich folgenden Code schreibe, funktioniert die Verbindung. Der User wird gebunden, alles gut.

Code: Alles auswählen

from ldap3 import Server, Connection, ALL, NTLM

server = Server(<IP und Port>, get_info=ALL)
conn = Connection(server, user="meinAdminUser", password="meinAdminPassword", auto_bind=True)
print(conn)
Antwort:

Code: Alles auswählen

ldap://<Server IP und Port> - cleartext - user:<meinAdminUser> - not lazy - bound - open - <local: <client IP und Port> - remote: <server IP ind Port> - tls not started - listening - SyncStrategy - internal decoder
So weit so gut. Ich weiss nun, dass grundsätzlich eine Verbindung zu Stande kommt.

Aber: Wie prüfe ich jetzt bei einem normalen User, ob der Username und das Passwort in LDAP vorkommt? Wenn ich im oberen Code einen normalen User abfrage, kommt eine Fehlermeldung....

Code: Alles auswählen

ldap3.core.exceptions.LDAPBindError: automatic bind not successful - invalidCredentials
Das macht für mich irgendwie noch Sinn, da der normale User wahrscheinlich keine Rechte hat. Ich denke, ich müsste nun den User über die "Admin-Verbindung" suchen und Name und Passwort prüfen. Aber wie mach ich das nun? Wie lautet das Attribut für Passwort? Und muss ich dieses erst noch hashen, da ich nicht annehme, das in LDAP das PW als Klartext daherkommt.

Sorry für meine (blöden) Fragen, aber es scheint, dass ich trotz intensivem Studium der Dokus, irgendwas noch so gar nicht verstanden habe.

Gruss RBaert
rbaert
User
Beiträge: 20
Registriert: Mittwoch 5. September 2018, 15:37

Ok, Ihr könnt die den vorherigen Post vergessen. Danke trotzdem.

Jetzt habe ich es geschafft mit dem Code von @einfachTobi. Danke sehr...

Der Fehler war simpel aber peinlich...

Ich habe diese Codezeile falsch interpretiert!!!

Code: Alles auswählen

app.config["LDAP_USER_SEARCH_SCOPE"] = "SUBTREE"
Ich dachte "SUBTREE" müsste ich auch auf meine Domäne anpassen. Als ich diesen nun ohne Änderung in den Code integriert habe, funktionierte alles.

Obwohl es mir peinlich dies zuzugeben... da der nächste aber sicher dankbar, wenn er sieht, dass die Lösung von einfachTobi funktioniert.

Danke allen
Gruss RBaert
einfachTobi
User
Beiträge: 491
Registriert: Mittwoch 13. November 2019, 08:38

Zur Erläuterung: SUBTREE im SEARCH_SCOPE bedeutet nur, dass auch alle Unterordner nach dem angegebenen Stichwort durchsucht werden. Schön, dass es funktioniert.
Antworten