Flask
Autorisatie en authenticatie
Zoeken…
Gebruik van de flask-login-extensie
Een van de eenvoudigere manieren om een autorisatiesysteem te implementeren, is het gebruik van de flask-login- extensie. De website van het project bevat een gedetailleerde en goed geschreven quickstart, waarvan een kortere versie beschikbaar is in dit voorbeeld.
Algemeen idee
De extensie onthult een aantal functies die worden gebruikt voor:
- gebruikers inloggen
- gebruikers uitloggen
- controleren of een gebruiker is ingelogd of niet en achterhalen welke gebruiker dat is
Wat het niet doet en wat u zelf moet doen:
- biedt geen manier om gebruikers op te slaan, bijvoorbeeld in de database
- biedt geen manier om de inloggegevens van de gebruiker te controleren, bijvoorbeeld gebruikersnaam en wachtwoord
Hieronder is een minimale set stappen nodig om alles werkend te krijgen.
Ik zou aanraden om alle auth-gerelateerde code in een aparte module of pakket te plaatsen, bijvoorbeeld auth.py
Op die manier kunt u de benodigde klassen, objecten of aangepaste functies afzonderlijk maken.
Maak een LoginManager
De extensie gebruikt een LoginManager
klasse die moet worden geregistreerd op uw Flask
toepassingsobject.
from flask_login import LoginManager
login_manager = LoginManager()
login_manager.init_app(app) # app is a Flask object
Zoals eerder LoginManager
kan LoginManager
bijvoorbeeld een globale variabele in een afzonderlijk bestand of pakket zijn. Vervolgens kan het worden geïmporteerd in het bestand waarin het Flask
object is gemaakt of in de fabrieksfunctie van uw toepassing en geïnitialiseerd.
Geef een callback op die wordt gebruikt voor het laden van gebruikers
Gebruikers worden normaal uit een database geladen. De terugbelactie moet een object retourneren dat een gebruiker vertegenwoordigt die overeenkomt met de opgegeven ID. Het moet None
teruggeven als de ID niet geldig is.
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id) # Fetch the user from the database
Dit kan direct onder het maken van uw LoginManager
worden gedaan.
Een klasse die uw gebruiker vertegenwoordigt
Zoals vermeld moet de callback user_loader
een object retourneren dat een gebruiker vertegenwoordigt. Wat betekent dat precies? Dat object kan bijvoorbeeld een wrapper zijn rond gebruikersobjecten die zijn opgeslagen in uw database of eenvoudigweg een model uit uw database. Dat object moet de volgende methoden en eigenschappen implementeren. Dat betekent dat als de callback uw databasemodel retourneert, u ervoor moet zorgen dat de genoemde eigenschappen en methoden aan uw model worden toegevoegd.
is_authenticated
Deze eigenschap moet
True
retourneren als de gebruiker is geverifieerd, dat wil zeggen dat deze geldige inloggegevens hebben verstrekt. U wilt ervoor zorgen dat de objecten die uw gebruikers vertegenwoordigen door de callback vanuser_loader
geretourneerdTrue
voor die methode zijn.is_active
Deze eigenschap moet True retourneren als dit een actieve gebruiker is. Ze zijn niet alleen geverifieerd, maar hebben ook hun account geactiveerd, niet opgeschort of een andere voorwaarde die uw toepassing heeft voor het weigeren van een account. Inactieve accounts kunnen zich niet aanmelden. Als u niet over een dergelijk mechanisme beschikt, retourneert u
True
van deze methode.is_anonymous
Deze eigenschap moet True retourneren als dit een anonieme gebruiker is. Dat betekent dat uw gebruikersobject dat wordt geretourneerd door de callback
user_loader
True
moet retourneren.get_id()
Deze methode moet een unicode retourneren die deze gebruiker op unieke wijze identificeert en kan worden gebruikt om de gebruiker te laden vanuit de callback van
user_loader
. Merk op dat dit een unicode moet zijn - als de ID van nature een int of een ander type is, moet u deze naar unicode converteren. Als de callbackuser_loader
objecten uit de database retourneert, retourneert deze methode hoogstwaarschijnlijk de database-ID van deze specifieke gebruiker. Dezelfde ID moet er natuurlijk voor zorgen dat de callbackuser_loader
later dezelfde gebruiker retourneert.
Als u dingen voor uzelf gemakkelijker wilt maken (** het wordt in feite aanbevolen), kunt u van UserMixin
erven in het object dat wordt geretourneerd door de callback van user_loader
(vermoedelijk een databasemodel). U kunt zien hoe die methoden en eigenschappen worden uitgevoerd door standaard in deze mixin hier .
Inloggen van de gebruikers
De extensie laat de validatie van de gebruikersnaam en het wachtwoord dat door de gebruiker is ingevoerd, aan u over. In feite maakt de extensie niet uit of u een combinatie van gebruikersnaam en wachtwoord of een ander mechanisme gebruikt. Dit is een voorbeeld voor het aanmelden van gebruikers met gebruikersnaam en wachtwoord.
@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)
Over het algemeen wordt het aanmelden van gebruikers bereikt door login_user aan te roepen en een exemplaar van een object door te geven dat uw eerder genoemde gebruiker vertegenwoordigt. Zoals getoond zal dit meestal gebeuren na het ophalen van de gebruiker uit de database en het valideren van zijn inloggegevens, maar het gebruikersobject verschijnt gewoon magisch in dit voorbeeld.
Ik heb een gebruiker ingelogd, wat nu?
Het object dat wordt geretourneerd door de callback user_loader
is op meerdere manieren toegankelijk.
In sjablonen:
De extensie injecteert het automatisch onder de naam
current_user
met behulp van een sjablooncontextprocessor. Om dat gedrag uit te schakelen en uw aangepaste processor te gebruiken,add_context_processor=False
in uwLoginManager
constructor.{% if current_user.is_authenticated %} Hi {{ current_user.name }}! {% endif %}
In Python-code:
De extensie biedt een verzoekgebonden object met de naam
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!'
Snel de toegang beperken met een decorateur Een
login_required
decorateur kan worden gebruikt om de toegang snel te beperken.from flask_login import login_required @app.route("/settings") @login_required def settings(): pass
Gebruikers afmelden
Gebruikers kunnen worden uitgelogd door logout_user()
aan te roepen. Het lijkt erop dat dit veilig is om te doen, zelfs als de gebruiker niet is ingelogd, zodat de @login_required
decorateur waarschijnlijk kan worden weggelaten.
@app.route("/logout")
@login_required
def logout():
logout_user()
return redirect(somewhere)
Wat gebeurt er als een gebruiker niet is aangemeld en ik toegang heb tot het object current_user
?
Standaard wordt een AnonymousUserMixin geretourneerd:
-
is_active
enis_authenticated
zijnFalse
-
is_anonymous
isTrue
-
get_id()
retourneertNone
Om een ander object voor anonieme gebruikers te gebruiken, moet u een opvraagbare functie (een klasse- of fabrieksfunctie) LoginManager
die anonieme gebruikers voor uw LoginManager
met:
login_manager.anonymous_user = MyAnonymousUser
Wat nu?
Hiermee is de basisintroductie van de extensie afgesloten. Voor meer informatie over configuratie en extra opties wordt het ten zeerste aanbevolen om de officiële gids te lezen .
Time-out van de inlogsessie
Het is een goede gewoonte om na een bepaalde tijd een time-out te krijgen voor de ingelogde sessie, u kunt dat bereiken met 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)
De standaardlevensduur van de sessie is 31 dagen, de gebruiker moet de inlogvernieuwingsweergave opgeven in geval van een time-out.
app.permanent_session_lifetime = timedelta(minutes=5)
Bovenstaande regel zal de gebruiker dwingen om elke 5 minuten opnieuw in te loggen.