====== LU06i - Authentifizierung mit Flask-Login ======
Flask-Login ist eine Erweiterung für Flask, die Benutzersitzungen handhabt und es einfach macht, Funktionen wie ''Login'', ''Logout'' und ''Remember Me'' zu implementieren. Flask-Login verwendet die Session-Funktionalität von Flask, um den angemeldeten Benutzer zu speichern.
==== Installation ====
Zuerst müssen wir Flask-Login installieren, dazu passen wir das requirements.txt an:
...
Flask-Login==0.6.3
==== Grundlegende Einrichtung ====
Nach der Installation müssen wir Flask-Login in unserer Anwendung initialisieren:
from flask_login import LoginManager
login_manager = LoginManager()
login_manager.init_app(app)
==== Benutzerklasse ====
Die Benutzerklasse muss einige spezielle Methoden erfüllen, die von Flask-Login verwendet werden: ''get_id()'',
''is_authenticated'', ''is_active'' und ''is_anonymous''. Im Allgemeinen kann dies durch die Erweiterung der Benutzerklasse mit der ''UserMixin''-Klasse von Flask-Login erreicht werden:
from flask_login import UserMixin
class User(UserMixin):
def __init__(self, user_id, username, email, password):
self.id = user_id
self.username = username
self.email = email
self.password = password
==== Benutzer-DAO-Klasse ====
Um den User in der Datenbank zu speichern, müssen wir eine entsprechende DAO-Klasse erstellen:
import sqlite3
class UserDao:
def __init__(self, db_file):
self.conn = sqlite3.connect(db_file, check_same_thread=False)
self.cursor = self.conn.cursor()
def create_user_table(self):
self.cursor.execute('''CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username TEXT, email TEXT, password TEXT)''')
self.conn.commit()
def add_user(self, user):
self.cursor.execute("INSERT INTO users (username, email, password) VALUES (?, ?, ?)", (user.username, user.email, user.password))
self.conn.commit()
def get_user_by_id(self, user_id):
self.cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
row = self.cursor.fetchone()
if row:
return User(row[0], row[1], row[2], row[3])
return None
def get_user_by_username(self, username):
self.cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
row = self.cursor.fetchone()
if row:
return User(row[0], row[1], row[2], row[3])
return None
def delete_user(self, user_id):
self.cursor.execute("DELETE FROM users WHERE id = ?", (user_id,))
if self.cursor.rowcount > 0:
self.conn.commit()
return True
return False
def close(self):
self.conn.close()
Diese DAO-Klasse bietet Methoden zum Erstellen der User-Tabelle, zum Hinzufügen von Benutzern und zum Abrufen von Benutzern anhand ihrer ID oder ihres Benutzernamens.
==== Benutzer-Loader und DAO-Integration ====
Die ''user_loader''-Funktion ist ein wesentlicher Bestandteil beim Einsatz von Flask-Login. Diese Funktion ist verantwortlich für das Laden eines Benutzerobjekts basierend auf der Benutzer-ID, die in der Session gespeichert ist. Wenn ein Benutzer sich einloggt, wird seine ID in der Flask-Session gespeichert. Bei nachfolgenden Anfragen wird diese ID verwendet, um den zugehörigen Benutzer zu laden und in das ''current_user''-Objekt zu speichern. Dadurch weiß die Anwendung während der gesamten Lebensdauer der Session, wer der aktuelle Benutzer ist.
Der ''@login_manager.user_loader''-Dekorator markiert die Funktion, die für das Laden des Benutzers zuständig ist. Diese Funktion erhält die Benutzer-ID als Argument, führt die notwendigen Schritte zur Benutzeridentifizierung durch und gibt das entsprechende Benutzerobjekt zurück. In unserem Fall verwendet die ''user_loader''-Funktion die ''get_user_by_id''-Methode aus der ''UserDao''-Klasse.
@login_manager.user_loader
def load_user(user_id):
return user_dao.get_user_by_id(int(user_id))
Das Definieren einer ''user_loader''-Funktion ist unerlässlich für das Funktionieren der Flask-Login-Erweiterung, da sie nicht selbstständig weiß, wie Benutzerobjekte aus der Session-ID geladen werden sollen.
==== Login und DAO-Integration ====
Die Login-Funktion wird die ''get_user_by_username''-Methode verwenden, um den User zu finden:
from flask_login import login_required, login_user, logout_user
app = Flask(__name__)
app.secret_key = 'supersecretkey' # Add a Secret-Key to the Flask App
@app.route('/login', methods=['POST'])
def login():
data = request.get_json()
user = user_dao.get_user_by_username(data['username'])
if user and user.password == data['password']:
login_user(user)
return jsonify({'success': True}), 200
return jsonify({'error': 'Invalid username or password'}), 401
@app.route('/logout')
@login_required
def logout():
logout_user()
return jsonify({'success': True}), 200
==== Schutz von Endpunkten ====
Um Endpunkte zu schützen, können wir den ''@login_required''-Dekorator verwenden:
@app.route('/shoppingitems', methods=['GET'])
@login_required
def get_shopping_items():
# Implementierung
----
{{tag>M323-LU06}}
[[https://creativecommons.org/licenses/by-nc-sa/4.0/ch/|{{https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png}}]] (c) Kevin Maurizi