Authentification de flacon avec LDAP

Flask est un framework micro Web basé sur Python qui vous permet d’écrire vos applications Web rapidement et efficacement. En micro, cela ne veut pas dire que Flask manque de fonctionnalité. Il se réfère simplement au fait que Flask a gardé son noyau petit et très extensible.

LDAP (Lightweight Directory Access Protocol) peut avoir différentes significations pour différentes personnes en fonction de leur utilisation. Il s'agit d'un protocole Internet permettant de rechercher des informations de contact sur les utilisateurs, des informations sur les certificats, les pointeurs réseau, etc., à partir d'un serveur où les données sont stockées dans une structure de style de répertoire. Son utilisation la plus courante consiste à fournir une "ouverture de session unique" permettant à un utilisateur d'accéder à plusieurs applications en se connectant une fois, le mot de passe étant partagé entre plusieurs services..

Dans ce didacticiel, je vais vous expliquer comment implémenter l'authentification d'utilisateurs dans votre application Flask à l'aide de LDAP. Pour illustrer cela, je vais créer une petite application avec une page d'accueil et une page de connexion. L'utilisateur devra entrer les informations de connexion sur la page de connexion. Si les informations d'identification entrées par l'utilisateur sont authentifiées avec succès sur le serveur LDAP fourni, l'utilisateur sera connecté. Si ce n'est pas le cas, un message approprié s'affiche..

Je suppose que vous avez une connaissance de base des meilleures pratiques en matière de création de flacon, LDAP, Flask-Login et de configuration d’environnement à l’aide de virtualenv, à suivre lors du développement d’une application Python..

Installation de dépendances

Les packages suivants doivent être installés pour l'application que nous allons développer.

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

Les commandes ci-dessus doivent installer tous les packages requis pour que cette application fonctionne..

Structure d'application

Tout d'abord, l'application doit être structurée de manière à être facilement compréhensible..

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

Tous les fichiers seront discutés ci-dessous. le statique dossier contient les fichiers standard Bootstrap CSS et JS.

L'application elle-même

Tout d'abord, le fichier de configuration doit être écrit:

flask_app / my_app / __ init__.py

depuis une importation de flacon Flask depuis flask.ext.sqlalchemy import SQLAlchemy depuis flask.ext.login import LoginManager app = Flask (__ name__) app.config ['SQLALCHEMY_DATABASE_URI'] = 'sqlite: ////tmp/test.db'. config ['WTF_CSRF_SECRET_KEY'] = 'clé aléatoire pour le formulaire' app.config ['LDAP_PROVIDER_URL'] = 'ldap: //ldap.testathon.net: 389 /' app.config ['LDAP_PROTOCOL_VERSION'] 3 c. app) app.secret_key = 'some_random_key' login_manager = LoginManager () login_manager.init_app (app) login_manager.login_view = 'login' de my_app.auth.views importer l'autorisation app.register_blueprint (auth) db.create_all ()

Dans le fichier ci-dessus, l'application a été configurée avec différentes options requises par les extensions ainsi que par la configuration LDAP. Ceci est suivi de l'initialisation des extensions et enfin de la création de la base de données. 

La dernière instruction crée une nouvelle base de données à l’emplacement indiqué SQLALCHEMY_DATABASE_URI si une base de données n'existe pas déjà à cet emplacement, sinon l'application sera chargée avec la même base de données.

flask_app / my_app / auth / models.py

import ldap de flask_wtf import Form Form from wtforms import TextField, PasswordField from wtforms.validators import InputRequired de ma db import db, app def get_ldap_connection (): conn = ldap.initialize (app.config ['LDAP_PROVIDER_URL']) .Model): id = db.Column (db.Integer, primary_key = True) nom d'utilisateur = db.Column (db.String (100)) def __init __ (self, nom d'utilisateur, mot de passe): self.username = nom d'utilisateur @staticmethod def try_login (nom d'utilisateur, mot de passe): conn = get_ldap_connection () conn.simple_bind_s ('cn =% s, ou = utilisateurs, dc = testathon, dc = net'% nom d'utilisateur, mot de passe) def is_authenticated (self): return True def is_active (self) ): return True def is_anonymous (self): return False def get_id (self): return unicode (self.id) class LoginForm (Form): username = TextField ('Nomutilisateur', [InputRequired ()]) password = PasswordField (' Mot de passe ', [InputRequired ()])

Le fichier ci-dessus commence par la création d'un Utilisateur modèle qui contient seulement un Nom d'utilisateur terrain à des fins de démonstration. Vous pouvez ajouter autant de champs que nécessaire en fonction du contexte de l'application.. 

Les méthodes is_authenticated ()c'est actif()is_anonymous () et get_id () sont requis par l'extension Flask-Login. le try_login () méthode effectue le processus d’authentification en créant d’abord une connexion avec le serveur LDAP, puis en utilisant le nom d’utilisateur et le mot de passe pour se connecter au serveur en créant une simple liaison. 

Le premier argument pris par le simple_bind_s () La méthode est le DN fourni par le serveur LDAP et varie en fonction de la configuration de l'enregistrement LDAP. Le traitement du formulaire est pris en charge par le Formulaire de connexion, qui étend la Forme classe fournie par Flask-WTForms.

flask_app / my_app / auth / views.py

'import ldap de la demande d'importation de flacon, render_template, flash, redirect, \ url_for, Blueprint, g de flask.ext.login import current_user, login_user, \ logout_user, login_required de my_app import login_manager, db de my_app.auth.models import User, LoginForm auth = Blueprint ('auth', __name__) @ login_manager.user_loader def load_user (id): renvoie User.query.get (int (id)) @ auth.before_request def get_current_user (): g.user = utilisateur_en cours @auth. route ('/') @ auth.route ('/ home') def home (): renvoie render_template ('home.html') @ auth.route ('/ login', methods = ['GET', 'POST' ]) def login (): if current_user.is_authenticated (): flash ('Vous êtes déjà connecté.') renvoie la redirection (url_for ('auth.home')) form = LoginForm (request.form) if request.method = = 'POST' et form.validate (): nom d'utilisateur = request.form.get ('nom d'utilisateur') password = request.form.get ('mot de passe') essayer: User.try_login (nom d'utilisateur, mot de passe) sauf ldap.INVALID_CREDENTIALS: flash ('Nom d'utilisateur ou mot de passe invalide. Veuillez réessayer.', 'danger' ) return render_template ('login.html', form = form) user = User.query.filter_by (nom d'utilisateur = username) .first () si pas user: user = utilisateur (nom d'utilisateur, mot de passe) db.session.add (utilisateur) db.session.commit () login_user (utilisateur) flash ('Vous vous êtes connecté avec succès.', 'success') retournez la redirection (url_for ('auth.home')) si 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 '))

Dans le fichier ci-dessus, les méthodes load_user () et get_current_user () sont requis par l'extension Flask-Login. Ensuite sont les gestionnaires pour notre application, qui sont décorés par leurs routes respectives.

maison() rend juste la page d'accueil pour l'utilisateur. Le contenu de la page d'accueil est déterminé par le modèle flask_app / my_app / templates / home.html, dont nous discuterons sous peu.

Le gestionnaire d'intérêt principal est s'identifier() car il gère le processus de connexion complet. Si un utilisateur connecté essaie d'accéder à cette page, celle-ci sera automatiquement redirigée vers la page d'accueil. Sinon, le processus de connexion commencera lorsque le nom d'utilisateur et le mot de passe LDAP de l'utilisateur sont pris en entrée de formulaire. flask_app / my_app / templates / login.html

À l'aide de ces informations d'identification, l'application tente d'authentifier l'utilisateur à partir du serveur LDAP fourni dans la configuration décrite précédemment. Si l'utilisateur est authentifié, l'application crée un nouvel enregistrement pour l'utilisateur si un nouvel utilisateur accède à l'application. Sinon, il connecte simplement l'utilisateur avec l'enregistrement existant de l'utilisateur..

Les messages flash sont montrés à l'utilisateur au fur et à mesure des besoins pour le maintenir en contact avec l'application.

Connectez - Out() hander efface simplement la session de l'utilisateur actuellement connecté, à la suite de quoi l'utilisateur est déconnecté.

flask_app / my_app / templates / base.html

      Didacticiel sur l'authentification par flacon avec LDAP     
Flask LDAP Demo

% pour la catégorie, message dans get_flashed_messages (with_categories = true)%
message
% endfor%
% block container% % endblock%
% block scripts% % endblock%

Le fichier de base ci-dessus contient l’en-tête, le pied de page et d’autres composants de base qui restent communs dans l’application. Cela aide à garder les modèles très modulaires et faciles à comprendre car chaque modèle ne contient que le code correspondant à son gestionnaire et à ses fonctionnalités.. 

Même si tous les composants communs sont définis ici, j’ai ajouté un bloc vide pour des scripts qui peut être étendu dans n'importe quel modèle qui hérite base.html. Notez comment le clignotement des messages est effectué ci-dessus et comment les classes CSS Bootstrap sont lues de manière dynamique pour que la boîte d'alerte de message flash soit stylée de manière appropriée..

le récipient le bloc sera prolongé par le reste des modèles pour ajouter leur contenu respectif.

flask_app / my_app / templates / home.html

% extend 'base.html'% % le conteneur de blocs% 

Bienvenue dans la démonstration de l'authentification Flask-LDAP

% if current_user.is_authenticated ()%

Hey current_user.username!!

Cliquez ici pour vous déconnecter % else% Cliquez ici pour vous connecter avec LDAP % endif% % endblock%

Notez que le modèle de base a été étendu et que le contenu de la page d'accueil a été ajouté à l'intérieur du conteneur de blocs..

Si l'utilisateur est connecté, il reçoit le nom d'utilisateur et un message lui permettant de se déconnecter. Sinon, un message s'affiche pour que l'utilisateur se connecte avec le lien vers la page de connexion..

flask_app / my_app / templates / login.html

% extended 'home.html'% % le conteneur de blocs% 
form.csrf_token
form.username.label: form.username ()
form.password.label: form.password ()
% endblock%

Le modèle de connexion contient simplement un formulaire avec des champs pour Nom d'utilisateur et mot de passe.

Lancer l'application

Pour exécuter l'application, exécutez le script run.py. Le contenu de ce script est:

depuis l'application d'importation my_app app.run (debug = True)

Maintenant, exécutez simplement depuis la ligne de commande:

python run.py

Enfin ouvrez http://127.0.0.1:5000/ dans votre navigateur préféré et voyez votre application en action. Tout devrait être explicite. Pour vous connecter, vous pouvez utiliser les informations d'identification suivantes:

  • stuart / stuart
  • carol / carol
  • John John

J'ai utilisé le serveur testathon qui a été mis en place par Stuart Lewis.

Conclusion

Au cours de ce didacticiel, nous avons construit une application Web petite mais efficace utilisant Flask à l'aide de l'extension Flask-Login. Cette application prend simplement un nom d'utilisateur et un mot de passe et authentifie l'utilisateur par rapport au serveur LDAP fourni. Utilisez votre imagination pour peaufiner et étendre l'application selon vos besoins.

Ressources

  • Flacon Documentation officielle
  • Page LDAP Wikipedia
  • Flask-Login Documentation officielle
  • Flask Framework Cookbook