Autenticazione del pallone con LDAP

Flask è un framework micro-web basato su Python che consente di scrivere le applicazioni Web in modo rapido ed efficiente. Con micro, non significa che Flask manchi di funzionalità. Si riferisce semplicemente al fatto che Flask ha mantenuto il suo nucleo piccolo ed altamente estensibile.

LDAP (Lightweight Directory Access Protocol) può avere significati diversi per persone diverse a seconda del loro utilizzo. Si tratta di un protocollo Internet per la ricerca di informazioni di contatto su utenti, informazioni su certificati, puntatori di rete, ecc. Da un server in cui i dati sono archiviati in una struttura di stile di directory. Il suo uso più diffuso è quello di fornire un "single sign on" in cui un utente può accedere a più applicazioni effettuando l'accesso una sola volta poiché la password sarà condivisa tra i servizi.

In questo tutorial, illustrerò come implementare l'autenticazione degli utenti nell'applicazione Flask utilizzando LDAP. Per dimostrarlo, creerò una piccola applicazione con una home page e una pagina di accesso. L'utente dovrebbe inserire i dettagli di accesso nella pagina di accesso. Se le credenziali immesse dall'utente vengono autenticate correttamente sul server LDAP fornito, l'utente effettuerà l'accesso. In caso contrario, all'utente verrà mostrato un messaggio appropriato.

Suppongo che tu abbia una conoscenza di base di Flask, LDAP, Flask-Login e best practice per l'installazione dell'ambiente che usano virtualenv per essere seguita mentre sviluppi un'applicazione Python.

Installazione di dipendenze

I seguenti pacchetti devono essere installati per l'applicazione che svilupperemo.

$ pip installa python-ldap $ pip installa flask-wtf flask-sqlalchemy flask-login

I comandi sopra riportati dovrebbero installare tutti i pacchetti richiesti necessari per far funzionare questa applicazione.

Struttura dell'applicazione

Per prima cosa l'applicazione deve essere strutturata in modo che sia facile da capire.

flask_app / my_app / - __init__.py auth / - __init__.py - models.py - views.py static / - css / - js / templates / - base.html - home.html - login.html - run.py

Tutti i file saranno discussi di seguito. Il statico cartella contiene i file standard Bootstrap CSS e JS.

L'applicazione stessa

Innanzitutto, è necessario scrivere il file di configurazione:

flask_app / my_app / __ init__.py

da flask import Flask da flask.ext.sqlalchemy import SQLAlchemy da flask.ext.login import LoginManager app = Flask (__ name__) app.config ['SQLALCHEMY_DATABASE_URI'] = 'sqlite: ////tmp/test.db' app. config ['WTF_CSRF_SECRET_KEY'] = 'chiave casuale per modulo' app.config ['LDAP_PROVIDER_URL'] = 'ldap: //ldap.testathon.net: 389 /' app.config ['LDAP_PROTOCOL_VERSION'] = 3 db = SQLAlchemy ( app) app.secret_key = 'some_random_key' login_manager = LoginManager () login_manager.init_app (app) login_manager.login_view = 'login' da my_app.auth.views importazione auth app.register_blueprint (auth) db.create_all ()

Nel file qui sopra, l'applicazione è stata configurata con diverse opzioni, come richiesto dalle estensioni e dalla configurazione LDAP. Questo è seguito dall'inizializzazione delle estensioni e infine dalla creazione del database. 

L'ultima istruzione crea un nuovo database nella posizione fornita contro SQLALCHEMY_DATABASE_URI se un database non esiste già in quella posizione, altrimenti carica l'applicazione con lo stesso database.

flask_app / my_app / auth / models.py

import ldap da flask_wtf import Form da wtforms import TextField, PasswordField da wtforms.validators import InputRequired da my_app import db, app def get_ldap_connection (): conn = ldap.initialize (app.config ['LDAP_PROVIDER_URL']) return conn class Utente (db .Model): id = db.Column (db.Integer, primary_key = True) username = db.Column (db.String (100)) def __init __ (self, username, password): self.username = username @staticmethod def try_login (username, password): conn = get_ldap_connection () conn.simple_bind_s ('cn =% s, ou = Utenti, dc = testathon, dc = net'% nome utente, password) def is_authenticated (self): return True def is_active (self ): return True def is_anonymous (self): return False def get_id (self): restituisce unicode (self.id) class LoginForm (Form): username = TextField ('Username', [InputRequired ()]) password = PasswordField (' Password ', [InputRequired ()])

Il file sopra inizia con la creazione di a Utente modello che contiene solo a nome utente campo per scopi dimostrativi. È possibile aggiungere tutti i campi necessari in base al contesto dell'applicazione. 

I metodi is_authenticated ()è attivo()is_anonymous ()get_id () sono necessari per l'estensione Flask-Login. Il try_login () metodo esegue l'effettivo processo di autenticazione creando prima una connessione con il server LDAP e quindi utilizzando il nome utente e la password per accedere al server creando un semplice binding. 

Il primo argomento assunto dal simple_bind_s () metodo è il DN, che viene fornito dal server LDAP e varia con la configurazione del record LDAP. La gestione della forma è curata da LoginForm, che estende il Modulo classe fornita da Flask-WTForms.

flask_app / my_app / auth / views.py

'importa ldap dalla richiesta di importazione del pallone, render_template, flash, reindirizza, \ url_for, Blueprint, g da flask.ext.login import current_user, login_user, \ logout_user, login_required da my_app import login_manager, db da my_app.auth.models import User, LoginForm auth = Blueprint ('auth', __name__) @ login_manager.user_loader def load_user (id): restituisce User.query.get (int (id)) @ auth.before_request def get_current_user (): g.user = current_user @auth. route ('/') @ auth.route ('/ home') def home (): restituisce render_template ('home.html') @ auth.route ('/ login', methods = ['GET', 'POST' ]) def login (): se current_user.is_authenticated (): flash ('Sei già connesso.') return redirect (url_for ('auth.home')) form = LoginForm (request.form) if request.method = = 'POST' e form.validate (): username = request.form.get ('username') password = request.form.get ('password') prova: User.try_login (username, password) tranne ldap.INVALID_CREDENTIALS: flash ('Nome utente o password non validi. Riprova.', 'pericolo' ) return render_template ('login.html', form = form) user = User.query.filter_by (username = username) .first () se non utente: utente = utente (username, password) db.session.add (utente) db.session.commit () login_user (utente) flash ('Hai eseguito correttamente l'accesso.', 'successo') restituisce il reindirizzamento (url_for ('auth.home')) if form.errors: flash (form.errors, ' danger ') return render_template (' login.html ', form = form) @ auth.route (' / logout ') @login_required def logout (): logout_user () return redirect (url_for (' auth.home '))

Nel file sopra, i metodi load_user () e get_current_user () sono necessari per estensione Flask-Login. Successivamente ci sono i gestori della nostra applicazione, che sono decorati dai rispettivi percorsi.

casa() rende solo la home page per l'utente. Il contenuto della home page è determinato dal modello flask_app / my_app / templates / home.html, di cui parleremo a breve.

Il gestore di interesse primario è accesso() mentre gestisce la procedura di accesso completa. Se un utente connesso tenta di accedere a questa pagina, la pagina reindirizzerà automaticamente alla pagina iniziale. In caso contrario, inizierà il processo di login in cui il nome utente e la password LDAP dell'utente vengono presi come input da flask_app / my_app / templates / login.html

Utilizzando queste credenziali, l'applicazione tenta di autenticare l'utente dal server LDAP fornito nella configurazione che abbiamo visto in precedenza. Se l'utente è autenticato, l'applicazione crea un nuovo record per l'utente se un utente che accede per la prima volta all'applicazione, altrimenti registra l'utente con il record esistente dell'utente.

I messaggi flash vengono mostrati all'utente come e quando richiesto per mantenere l'utente impegnato con l'applicazione.

disconnettersi() hander cancella semplicemente la sessione dell'utente attualmente connesso a seguito della quale l'utente è disconnesso.

flask_app / my_app / templates / base.html

      Autenticazione pallone con tutorial LDAP     
Demo LDAP pallone

% per categoria, messaggio in get_flashed_messages (with_categories = true)%
Messaggio
% endfor%
% block container% % endblock%
% block scripts% % endblock%

Sopra è il file di base che contiene l'intestazione, il piè di pagina e altri componenti di base che rimangono comuni in tutta l'applicazione. Ciò aiuta a mantenere i modelli molto modulari e di facile comprensione in quanto ogni modello contiene solo il codice relativo al gestore e alle funzionalità. 

Anche se tutti i componenti comuni sono definiti qui, ho aggiunto un blocco vuoto per script che può essere esteso in qualsiasi modello che eredita base.html. Si noti come viene eseguito il flashing dei messaggi sopra e in che modo vengono riprodotte dinamicamente le classi CSS Bootstrap per rendere in modo appropriato la casella di avviso del messaggio flash.

Il contenitore il blocco verrà esteso dal resto dei modelli per aggiungere i rispettivi contenuti.

flask_app / my_app / templates / home.html

% estende 'base.html'% % block container% 

Benvenuti alla demo di autenticazione Flask-LDAP

% se current_user.is_authenticated ()%

Hey current_user.username!!

Fai clic qui per uscire % else% Fai clic qui per accedere con LDAP % endif% % endblock%

Si noti come il modello di base è stato esteso e il contenuto per la home page è stato aggiunto all'interno del contenitore del blocco.

Se l'utente ha effettuato il login, l'utente viene salutato con il nome utente e mostrato un messaggio per disconnettersi. In caso contrario, all'utente viene mostrato un messaggio per accedere con il collegamento alla pagina di accesso.

flask_app / my_app / templates / login.html

% estende 'home.html'% % block container% 
form.csrf_token
form.username.label: form.username ()
form.password.label: form.password ()
% endblock%

Il modello di accesso contiene semplicemente un modulo con i campi per nome utente e parola d'ordine.

Esecuzione dell'applicazione

Per eseguire l'applicazione, eseguire lo script run.py. I contenuti di questo script sono:

dall'app di importazione my_app app.run (debug = True)

Ora esegui dalla riga di comando:

python run.py

Infine apri http://127.0.0.1:5000/ nel tuo browser preferito e guarda la tua applicazione in azione. Tutto dovrebbe essere auto-esplicativo. Per accedere, puoi utilizzare le seguenti credenziali:

  • stuart / stuart
  • carol / carol
  • John / Giovanni

Ho usato il server di testathon che è stato creato da Stuart Lewis.

Conclusione

Nel corso di questo tutorial, abbiamo creato un'applicazione web piccola ma efficace utilizzando Flask con l'aiuto dell'estensione Flask-Login. Questa applicazione richiede semplicemente un nome utente e una password e autentica l'utente sul server LDAP fornito. Usa la tua immaginazione per modificare ed estendere l'applicazione secondo le tue esigenze.

risorse

  • Documentazione ufficiale del pallone
  • Pagina Wikipedia LDAP
  • Flask-Login Documentazione ufficiale
  • Libro di ricette di Flask Framework