Flask
Autorisation et authentification
Recherche…
Utilisation de l'extension flask-login
L'une des manières les plus simples d'implémenter un système d'autorisation consiste à utiliser l'extension flask-login . Le site Web du projet contient un quickstart détaillé et bien écrit, dont une version plus courte est disponible dans cet exemple.
Idée générale
L'extension expose un ensemble de fonctions utilisées pour:
- consigner les utilisateurs dans
- déconnecter les utilisateurs
- vérifier si un utilisateur est connecté ou non et trouver quel utilisateur est ce
Ce que ça ne fait pas et ce que vous devez faire vous-même:
- ne fournit pas un moyen de stocker les utilisateurs, par exemple dans la base de données
- ne fournit pas un moyen de vérifier les informations d'identification de l'utilisateur, par exemple le nom d'utilisateur et le mot de passe
Ci-dessous, il y a un ensemble minimal d'étapes nécessaires pour que tout fonctionne.
Je recommande de placer tous les codes associés à un auth dans un module ou un package distinct, par exemple auth.py
De cette façon, vous pouvez créer les classes, objets ou fonctions personnalisées nécessaires séparément.
Créez un LoginManager
L'extension utilise une classe LoginManager
qui doit être enregistrée sur votre objet d'application Flask
.
from flask_login import LoginManager
login_manager = LoginManager()
login_manager.init_app(app) # app is a Flask object
Comme mentionné précédemment, LoginManager
peut par exemple être une variable globale dans un fichier ou un package distinct. Ensuite, il peut être importé dans le fichier dans lequel l'objet Flask
est créé ou dans la fonction fabrique de l'application et initialisé.
Spécifiez un rappel utilisé pour le chargement des utilisateurs
Un utilisateur sera normalement chargé à partir d'une base de données. Le rappel doit retourner un objet qui représente un utilisateur correspondant à l'ID fourni. Il doit retourner None
si l'ID n'est pas valide.
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id) # Fetch the user from the database
Cela peut être fait directement sous la création de votre LoginManager
.
Une classe représentant votre utilisateur
Comme mentionné, le rappel user_loader
doit renvoyer un objet qui représente un utilisateur. Qu'est-ce que cela signifie exactement? Cet objet peut par exemple être une enveloppe autour des objets utilisateur stockés dans votre base de données ou simplement un modèle directement depuis votre base de données. Cet objet doit implémenter les méthodes et propriétés suivantes. Cela signifie que si le rappel renvoie votre modèle de base de données, vous devez vous assurer que les propriétés et méthodes mentionnées sont ajoutées à votre modèle.
is_authenticated
Cette propriété doit retourner
True
si l'utilisateur est authentifié, c'est-à-dire qu'il a fourni des informations d'identification valides. Vous souhaiterez vous assurer que les objets représentant vos utilisateurs renvoyés par le rappeluser_loader
renvoientTrue
pour cette méthode.is_active
Cette propriété doit renvoyer True s'il s'agit d'un utilisateur actif. En plus d'être authentifiée, elle a également activé son compte, n'a pas été suspendue ou toute autre condition de rejet d'un compte par votre application. Les comptes inactifs ne peuvent pas se connecter. Si vous ne disposez pas d'un tel mécanisme, retournez
True
partir de cette méthode.is_anonymous
Cette propriété doit renvoyer True s'il s'agit d'un utilisateur anonyme. Cela signifie que votre objet utilisateur renvoyé par le rappel
user_loader
doit retournerTrue
.get_id()
Cette méthode doit renvoyer un Unicode qui identifie de manière unique cet utilisateur et peut être utilisé pour charger l'utilisateur à partir du rappel
user_loader
. Notez que ce doit être un Unicode - si l'ID est nativement un int ou un autre type, vous devrez le convertir en Unicode. Si le rappeluser_loader
renvoie des objets de la base de données, cette méthode retournera très probablement l'ID de base de données de cet utilisateur particulier. Bien entendu, le même identifiant doit provoquer le rappel deuser_loader
ultérieurement.
Si vous voulez vous faciliter les choses (** c'est en fait recommandé), vous pouvez hériter de UserMixin
dans l'objet renvoyé par le rappel de user_loader
(probablement un modèle de base de données). Vous pouvez voir comment ces méthodes et propriétés sont implémentées par défaut dans ce mixin ici .
Connecter les utilisateurs dans
L'extension vous laisse la validation du nom d'utilisateur et du mot de passe saisis par l'utilisateur. En fait, l'extension ne se soucie pas si vous utilisez un nom d'utilisateur et mot de passe combo ou un autre mécanisme. Ceci est un exemple de journalisation des utilisateurs utilisant le nom d'utilisateur et le mot de passe.
@app.route('/login', methods=['GET', 'POST'])
def login():
# Here we use a class of some kind to represent and validate our
# client-side form data. For example, WTForms is a library that will
# handle this for us, and we use a custom LoginForm to validate.
form = LoginForm()
if form.validate_on_submit():
# Login and validate the user.
# user should be an instance of your `User` class
login_user(user)
flask.flash('Logged in successfully.')
next = flask.request.args.get('next')
# is_safe_url should check if the url is safe for redirects.
# See http://flask.pocoo.org/snippets/62/ for an example.
if not is_safe_url(next):
return flask.abort(400)
return flask.redirect(next or flask.url_for('index'))
return flask.render_template('login.html', form=form)
En général, la journalisation des utilisateurs est effectuée en appelant login_user et en lui transmettant une instance d'un objet représentant votre utilisateur. Comme indiqué, cela se produit généralement après la récupération de l'utilisateur de la base de données et la validation de ses informations d'identification, mais l'objet utilisateur apparaît comme par magie dans cet exemple.
Je me suis connecté à un utilisateur, et maintenant?
L'objet renvoyé par le rappel user_loader
est accessible de plusieurs manières.
Dans les modèles:
L'extension l'injecte automatiquement sous le nom
current_user
aide d'un processeur de contexte de modèle. Pour désactiver ce comportement et utiliser votre processeur personnalisé, définissezadd_context_processor=False
dans votre constructeurLoginManager
.{% if current_user.is_authenticated %} Hi {{ current_user.name }}! {% endif %}
En code Python:
L'extension fournit un objet lié à la requête appelé
current_user
.from flask_login import current_user @app.route("/hello") def hello(): # Assuming that there is a name property on your user object # returned by the callback if current_user.is_authenticated: return 'Hello %s!' % current_user.name else: return 'You are not logged in!'
Limiter l'accès rapidement en utilisant un décorateur Un décorateur
login_required
peut être utilisé pour limiter l'accès rapidement.from flask_login import login_required @app.route("/settings") @login_required def settings(): pass
Déconnexion des utilisateurs
Les utilisateurs peuvent être déconnectés en appelant logout_user()
. Il semble sûr de le faire même si l'utilisateur n'est pas connecté, de sorte que le décorateur @login_required
peut très probablement être utilisé.
@app.route("/logout")
@login_required
def logout():
logout_user()
return redirect(somewhere)
Que se passe-t-il si un utilisateur n'est pas connecté et que current_user
objet current_user
?
Par défaut, un AnonymousUserMixin est renvoyé:
-
is_active
etis_authenticated
sontFalse
-
is_anonymous
estTrue
-
get_id()
renvoieNone
Pour utiliser un objet différent pour les utilisateurs anonymes, fournissez un appelable (une fonction de classe ou de fabrique) qui crée des utilisateurs anonymes sur votre LoginManager
avec:
login_manager.anonymous_user = MyAnonymousUser
Quelle prochaine
Ceci conclut l'introduction de base à l'extension. Pour en savoir plus sur la configuration et les options supplémentaires, il est fortement recommandé de lire le guide officiel .
Délai de la session de connexion
Sa bonne pratique est d’arrêter la session après un certain temps, vous pouvez le faire avec Flask-Login.
from flask import Flask, session
from datetime import timedelta
from flask_login import LoginManager, login_require, login_user, logout_user
# Create Flask application
app = Flask(__name__)
# Define Flask-login configuration
login_mgr = LoginManager(app)
login_mgr.login_view = 'login'
login_mgr.refresh_view = 'relogin'
login_mgr.needs_refresh_message = (u"Session timedout, please re-login")
login_mgr.needs_refresh_message_category = "info"
@app.before_request
def before_request():
session.permanent = True
app.permanent_session_lifetime = timedelta(minutes=5)
La durée de vie par défaut de la session est de 31 jours, l'utilisateur doit spécifier la vue d'actualisation de la connexion en cas de dépassement du délai d'attente.
app.permanent_session_lifetime = timedelta(minutes=5)
La ligne ci-dessus forcera l'utilisateur à se reconnecter toutes les 5 minutes.