Einführung

Die Möglichkeit für Benutzer, sich bei Ihrer Anwendung anzumelden, ist eine der häufigsten Funktionen, die Sie Ihrer Webanwendung hinzufügen werden. Dieser Artikel behandelt, wie Sie Ihrer Flask-Anwendung mit dem Paket Flask-Login Authentifizierung hinzufügen können.

Wir werden einige Registrierungs- und Anmeldeseiten erstellen, die Benutzern die Anmeldung und den Zugriff auf geschützte Seiten ermöglichen, die nicht angemeldete Benutzer nicht sehen können. Wir werden Informationen aus dem Benutzermodell nehmen und sie auf unseren geschützten Seiten anzeigen, wenn sich der Benutzer anmeldet, um zu simulieren, wie ein Profil aussehen würde.

In diesem Artikel behandeln wir die folgenden Punkte:

  • Verwenden der Bibliothek Flask-Login für die Sitzungsverwaltung.
  • Verwenden des integrierten Dienstprogramms Flask für das Hashing von Passwörtern.
  • Hinzufügen von geschützten Seiten zu unserer Anwendung nur für angemeldete Benutzer.
  • Verwenden von Flask-SQLAlchemy zum Erstellen eines Benutzermodells.
  • Erstellen von Registrierungs- und Anmeldeformularen für unsere Benutzer zur Erstellung von Konten und zum Anmelden.
  • Zurückgeben von Fehlermeldungen an unsere Benutzer, wenn etwas schiefgeht.
  • Verwenden von Informationen aus dem Konto des Benutzers zur Anzeige auf der Profilseite.

Voraussetzungen

gen illustration for: Voraussetzungen

Um dieses Tutorial zu absolvieren, benötigen Sie Folgendes:

  • Vertrautheit mit einem Editor wie Visual Studio Code ist hilfreich, aber nicht erforderlich.

Unsere Anwendung wird das Flask Application Factory-Muster mit Blueprints verwenden. Wir werden eine Blueprint haben, die alles im Zusammenhang mit auth (Authentifizierung) behandelt, und eine weitere für unsere regulären Routen, die den Index und die geschützte Profilseite enthalten. In einer echten Anwendung können Sie die Funktionalität nach Belieben aufschlüsseln, aber die hier behandelte Lösung wird für dieses Tutorial gut funktionieren.

Hier ist ein Diagramm, das einen Eindruck davon vermittelt, wie die Dateistruktur Ihres Projekts nach Abschluss des Tutorials aussehen wird:

				
					
.

└── <^>flask_auth_app<^>

 └── project

 ├── __init__.py # setup our app

 ├── auth.py # the auth routes for our app

 ├── db.sqlite # our database

 ├── main.py # the non-auth routes for our app

 ├── models.py # our user model

 └── templates

 ├── base.html # contains common layout and links

 ├── index.html # show the home page

 ├── login.html # show the login form

 ├── profile.html # show the profile page

 └── signup.html # show the signup form

				
			

Im weiteren Verlauf des Tutorials werden wir diese Verzeichnisse und Dateien erstellen.

Schritt 1 — Installieren der Pakete

Es gibt drei Hauptpakete, die wir für unser Projekt benötigen:

  • Flask
  • Flask-Login: zur Handhabung der Benutzersitzungen nach der Authentifizierung
  • Flask-SQLAlchemy: zur Darstellung des Benutzermodells und als Schnittstelle zu unserer Datenbank

Wir verwenden SQLite, um keine zusätzlichen Abhängigkeiten für die Datenbank installieren zu müssen.

Zuerst beginnen wir mit der Erstellung des Projektverzeichnisses:

				
					
mkdir <^>flask_auth_app<^>

				
			

Als Nächstes müssen wir zum Projektverzeichnis navigieren:

				
					
cd <^>flask_auth_app<^>

				
			

Falls Sie keine Python-Umgebung haben, werden Sie eine erstellen wollen. Je nachdem, wie Python auf Ihrem Rechner installiert wurde, werden Ihre Befehle in etwa so aussehen:

				
					
python3 -m venv <^>auth<^>

source <^>auth<^>/bin/activate

				
			

Anmerkung: Sie können das für Ihre lokale Umgebung relevante Tutorial zur Einrichtung von venv konsultieren.

Führen Sie die folgenden Befehle aus Ihrer virtuellen Umgebung aus, um die erforderlichen Pakete zu installieren:

				
					
pip install flask flask-sqlalchemy flask-login

				
			

Nachdem Sie die Pakete installiert haben, können Sie nun die Hauptanwendungsdatei erstellen.

Schritt 2 — Erstellen der Hauptanwendungsdatei

Beginnen wir mit der Erstellung eines Verzeichnisses project:

				
					
mkdir project

				
			

Die erste Datei, an der wir arbeiten, wird die Datei __init__.py für unser Projekt sein:

				
					
nano project/__init__.py

				
			

Diese Datei wird die Funktion zum Erstellen unserer Anwendung haben, die die Datenbank initialisiert und unsere Blueprints registriert. Im Moment bringt das nicht viel, aber es wird für den Rest unserer Anwendung benötigt. Wir müssen SQLAlchemy initialisieren, einige Konfigurationswerte festlegen und unsere Blueprints registrieren.

				
					
[label project/__init__.py]

from flask import Flask

from flask_sqlalchemy import SQLAlchemy



# init SQLAlchemy so we can use it later in our models

db = SQLAlchemy()



def create_app():

 app = Flask(__name__)



 app.config['SECRET_KEY'] = '<^>secret-key-goes-here<^>'

 app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'



 db.init_app(app)



 # blueprint for auth routes in our app

 from .auth import auth as auth_blueprint

 app.register_blueprint(auth_blueprint)



 # blueprint for non-auth parts of app

 from .main import main as main_blueprint

 app.register_blueprint(main_blueprint)



 return app

				
			

Nachdem wir nun die Hauptanwendungsdatei haben, können wir mit dem Hinzufügen unserer Routen beginnen.

Schritt 3 — Hinzufügen von Routen

Für unsere Routen verwenden wir zwei Blueprints. Für unsere Haupt-Blueprint haben wir eine Startseite (/) und eine Profilseite (/profile) für nach der Anmeldung. Versucht der Benutzer, ohne angemeldet zu sein, auf die Profilseite zuzugreifen, wird er auf die Anmeldungsroute umgeleitet.

Für unsere Auth-Blueprint haben wir Routen, um sowohl die Anmeldeseite (/login) als auch die Registrierungsseite (/sign-up) abzurufen. Außerdem haben wir Routen zur Bearbeitung der POST-Anfragen von beiden Routen. Schließlich haben wir eine Abmeldungsroute (/logout), um einen aktiven Benutzer abzumelden.

Bis auf Weiteres definieren wir login, signup und logout mit einfachen Rückgaben. Wir werden sie in einem späteren Schritt erneut besuchen und mit der gewünschten Funktionalität aktualisieren.

Erstellen Sie zunächst main.py für Ihre main_blueprint:

				
					
nano project/main.py

				
			
				
					
[label project/main.py]

from flask import Blueprint

from . import db



main = Blueprint('main', __name__)



@main.route('/')

def index():

 return 'Index'



@main.route('/profile')

def profile():

 return 'Profile'

				
			

Erstellen Sie als Nächstes auth.py für Ihre auth_blueprint:

				
					
nano project/auth.py

				
			
				
					
[label project/auth.py]

from flask import Blueprint

from . import db



auth = Blueprint('auth', __name__)



@auth.route('/login')

def login():

 return 'Login'



@auth.route('/signup')

def signup():

 return 'Signup'



@auth.route('/logout')

def logout():

 return 'Logout'

				
			

In einem Terminal können Sie die Werte FLASK_APP und FLASK_DEBUG festlegen:

				
					
export FLASK_APP=project

export FLASK_DEBUG=1

				
			

Die Umgebungsvariable FLASK_APP weist Flask an, wie die Anwendung geladen werden soll. Sie sollte darauf zeigen, wo sich create_app befindet. Für unsere Bedürfnisse verweisen wir auf das Projektverzeichnis.

Die Umgebungsvariable FLASK_DEBUG wird durch Einstellung auf 1 aktiviert. Dadurch wird ein Debugger aktiviert, der Anwendungsfehler im Browser anzeigt.

Stellen Sie sicher, dass Sie sich im Verzeichnis <^>flask_auth_app<^> befinden, und führen Sie dann das Projekt aus:

				
					
flask run

				
			

Nun sollten Sie in einem Webbrowser in der Lage sein, zu den fünf möglichen URLs zu navigieren und den zurückgegebenen Text zu sehen, der in auth.py und main.py definiert wurde.

Wenn Sie beispielsweise localhost:5000/profile besuchen, wird angezeigt: Profile:

Nachdem wir nun verifiziert haben, dass sich unsere Routen wie erwartet verhalten, können wir mit der Erstellung von Vorlagen fortfahren.

Schritt 4 — Erstellen von Vorlagen

Fahren wir damit fort, die Vorlagen zu erstellen, die in unserer Anwendung verwendet werden. Dies ist der erste Schritt, bevor wir die tatsächliche Anmeldefunktionalität implementieren können. Unsere Anwendung verwendet vier Vorlagen:

  • index.html
  • profile.html
  • login.html
  • signup.html

Außerdem haben wir eine Basisvorlage, die einen gemeinsamen Code für jede der Seiten hat. In diesem Fall wird die Basisvorlage Navigationslinks und das allgemeine Layout der Seite enthalten. Lassen Sie uns diese jetzt erstellen.

Erstellen Sie zunächst ein Verzeichnis templates in dem Verzeichnis project:

				
					
mkdir -p project/templates

				
			

Erstellen Sie dann base.html:

				
					
nano project/templates/base.html

				
			

Fügen Sie als Nächstes den folgenden Code in die Datei base.html ein:

				
					
[label project/templates/base.html]

&lt;!DOCTYPE html&gt;

&lt;html&gt;



&lt;head&gt;

 &lt;meta charset="utf-8"&gt;

 &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;

 &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;

 &lt;title&gt;Flask Auth Example&lt;/title&gt;

 &lt;link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" /&gt;

&lt;/head&gt;



&lt;body&gt;

 &lt;section class="hero is-primary is-fullheight"&gt;



 &lt;div class="hero-head"&gt;

 &lt;nav class="navbar"&gt;

 &lt;div class="container"&gt;



 &lt;div id="navbarMenuHeroA" class="navbar-menu"&gt;

 &lt;div class="navbar-end"&gt;

 &lt;a href="{{ url_for('main.index') }}" class="navbar-item"&gt;

 Home

 &lt;/a&gt;

 &lt;a href="{{ url_for('main.profile') }}" class="navbar-item"&gt;

 Profile

 &lt;/a&gt;

 &lt;a href="{{ url_for('auth.login') }}" class="navbar-item"&gt;

 Login

 &lt;/a&gt;

 &lt;a href="{{ url_for('auth.signup') }}" class="navbar-item"&gt;

 Sign Up

 &lt;/a&gt;

 &lt;a href="{{ url_for('auth.logout') }}" class="navbar-item"&gt;

 Logout

 &lt;/a&gt;

 &lt;/div&gt;

 &lt;/div&gt;

 &lt;/div&gt;

 &lt;/nav&gt;

 &lt;/div&gt;



 &lt;div class="hero-body"&gt;

 &lt;div class="container has-text-centered"&gt;

 {% block content %}

 {% endblock %}

 &lt;/div&gt;

 &lt;/div&gt;

 &lt;/section&gt;

&lt;/body&gt;



&lt;/html&gt;

				
			

Dieser Code erstellt eine Reihe von Menülinks zu jeder Seite der Anwendung und einen Bereich, in dem der Inhalt angezeigt wird.

Anmerkung: Hinter den Kulissen verwenden wir Bulma, für das Styling und Layout. Für einen tieferen Einblick in Bulma sollten Sie die offizielle Bulma-Dokumentation lesen.

Erstellen Sie als Nächstes templates/index.html:

				
					
nano project/templates/index.html

				
			

Fügen Sie der neu erstellten Datei den folgenden Code hinzu, um Inhalte zu der Seite hinzuzufügen:

				
					
[label project/templates/index.html]

{% extends "base.html" %}



{% block content %}

&lt;h1 class="title"&gt;

 Flask Login Example

&lt;/h1&gt;

&lt;h2 class="subtitle"&gt;

 Easy authentication and authorization in Flask.

&lt;/h2&gt;

{% endblock %}

				
			

Dieser Code erstellt eine grundlegende Indexseite mit einem Titel und einem Untertitel.

Erstellen Sie als Nächstes templates/login.html:

				
					
nano project/templates/login.html

				
			

Dieser Code generiert eine Anmeldeseite mit Feldern für E-Mail und Passwort. Es gibt auch ein Kontrollkästchen zur „Erinnerung“ an eine angemeldete Sitzung.

				
					
[label project/templates/login.html]

{% extends "base.html" %}



{% block content %}

&lt;div class="column is-4 is-offset-4"&gt;

 &lt;h3 class="title"&gt;Login&lt;/h3&gt;

 &lt;div class="box"&gt;

 &lt;form method="POST" action="/login"&gt;

 &lt;div class="field"&gt;

 &lt;div class="control"&gt;

 &lt;input class="input is-large" type="email" name="email" placeholder="Your Email" autofocus=""&gt;

 &lt;/div&gt;

 &lt;/div&gt;



 &lt;div class="field"&gt;

 &lt;div class="control"&gt;

 &lt;input class="input is-large" type="password" name="password" placeholder="Your Password"&gt;

 &lt;/div&gt;

 &lt;/div&gt;

 &lt;div class="field"&gt;

 &lt;label class="checkbox"&gt;

 &lt;input type="checkbox"&gt;

 Remember me

 &lt;/label&gt;

 &lt;/div&gt;

 &lt;button class="button is-block is-info is-large is-fullwidth"&gt;Login&lt;/button&gt;

 &lt;/form&gt;

 &lt;/div&gt;

&lt;/div&gt;

{% endblock %}

				
			

Erstellen Sie als Nächstes templates/signup.html:

				
					
nano project/templates/signup.html

				
			

Fügen Sie den folgenden Code hinzu, um eine Registrierungsseite mit Feldern für E-Mail, Namen und Passwort zu erstellen:

				
					
[label project/templates/signup.html]

{% extends "base.html" %}



{% block content %}

&lt;div class="column is-4 is-offset-4"&gt;

 &lt;h3 class="title"&gt;Sign Up&lt;/h3&gt;

 &lt;div class="box"&gt;

 &lt;form method="POST" action="/signup"&gt;

 &lt;div class="field"&gt;

 &lt;div class="control"&gt;

 &lt;input class="input is-large" type="email" name="email" placeholder="Email" autofocus=""&gt;

 &lt;/div&gt;

 &lt;/div&gt;



 &lt;div class="field"&gt;

 &lt;div class="control"&gt;

 &lt;input class="input is-large" type="text" name="name" placeholder="Name" autofocus=""&gt;

 &lt;/div&gt;

 &lt;/div&gt;



 &lt;div class="field"&gt;

 &lt;div class="control"&gt;

 &lt;input class="input is-large" type="password" name="password" placeholder="Password"&gt;

 &lt;/div&gt;

 &lt;/div&gt;



 &lt;button class="button is-block is-info is-large is-fullwidth"&gt;Sign Up&lt;/button&gt;

 &lt;/form&gt;

 &lt;/div&gt;

&lt;/div&gt;

{% endblock %}

				
			

Erstellen Sie als Nächstes templates/profile.html:

				
					
nano project/templates/profile.html

				
			

Fügen Sie diesen Code hinzu, um eine einfache Seite mit einem Titel zu erstellen, der fest programmiert ist, um Anthony willkommen zu heißen:

				
					
[label project/templates/profile.html]

{% extends "base.html" %}



{% block content %}

&lt;h1 class="title"&gt;

 Welcome, Anthony!

&lt;/h1&gt;

{% endblock %}

				
			

Später fügen wir Code hinzu, um jeden Benutzer dynamisch zu begrüßen.

Sobald Sie die Vorlagen hinzugefügt haben, können wir die Return-Anweisungen in jeder der uns zur Verfügung stehenden Routen aktualisieren, um die Vorlage anstelle des Textes zurückzugeben.

Aktualisieren Sie als Nächstes main.py durch Ändern der Importzeile und der Routen für index und profile:

				
					
[label project/main.py]

from flask import Blueprint&lt;^&gt;, render_template&lt;^&gt;

...

@main.route('/')

def index():

 return &lt;^&gt;render_template('index.html')&lt;^&gt;



@main.route('/profile')

def profile():

 return &lt;^&gt;render_template('profile.html')&lt;^&gt;

				
			

Jetzt aktualisieren Sie auth.py durch Ändern der Importzeile und Routen für login und signup:

				
					
[label project/auth.py]

from flask import Blueprint, render_template

...

@auth.route('/login')

def login():

 return &lt;^&gt;render_template('login.html')&lt;^&gt;



@auth.route('/signup')

def signup():

 return &lt;^&gt;render_template('signup.html')&lt;^&gt;

				
			

Sobald Sie diese Änderungen vorgenommen haben, sieht die Registrierungsseite wie folgt aus, wenn Sie zu /sign-up navigieren:

Sie sollten auch die Seiten für /, /login und /profile sehen können.

Wir lassen /logout vorerst in Ruhe, da es keine Vorlage anzeigt, wenn wir fertig sind.

Schritt 5 — Erstellen von Benutzermodellen

Unser Benutzermodell stellt dar, was es für unsere Anwendung bedeutet, einen Benutzer zu haben. Wir haben Felder für eine E-Mail-Adresse, ein Passwort und einen Namen. In Ihrer Anwendung können Sie entscheiden, ob Sie mehr Informationen pro Benutzer speichern möchten. Sie können Dinge wie Geburtstag, Profilbild, Ort oder beliebige Benutzereinstellungen hinzufügen.

In Flask-SQLAlchemy erstellte Modelle werden durch Klassen dargestellt, die dann in Tabellen in einer Datenbank übersetzt werden. Die Attribute dieser Klassen werden dann zu Spalten für diese Tabellen.

Lassen Sie uns fortfahren und dieses Benutzermodell erstellen:

				
					
nano project/models.py

				
			

Dieser Code erstellt ein Benutzermodell mit Spalten für id, email, password und name:

				
					
[label project/models.py]

from . import db



class User(db.Model):

 id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy

 email = db.Column(db.String(100), unique=True)

 password = db.Column(db.String(100))

 name = db.Column(db.String(1000))

				
			

Nachdem Sie ein Benutzermodell erstellt haben, können Sie nun mit der Konfiguration Ihrer Datenbank fortfahren.

Schritt 6 — Konfigurieren der Datenbank

Wie in den Voraussetzungen angegeben, verwenden wir eine SQLite-Datenbank. Wir könnten selbst eine SQLite-Datenbank erstellen, aber lassen wir das Flask SQLAlchemy für uns erledigen: Wir haben den Pfad der Datenbank bereits in der Datei __init__.py angegeben. Daher müssen wir Flask-SQLAlchemy nur anweisen, die Datenbank in der Python REPL zu erstellen.

Wenn Sie Ihre Anwendung stoppen und eine Python REPL öffnen, können wir die Datenbank mit der Methode create_all auf dem Objekt db erstellen. Stellen Sie sicher, dass Sie sich immer noch in der virtuellen Umgebung und im Verzeichnis <^>flask_auth_app<^> befinden.

				
					
from project import db, create_app, models

db.create_all(app=create_app()) # pass the create_app result so Flask-SQLAlchemy gets the configuration.

				
			

Anmerkung: Wenn die Verwendung des Python-Interpreters für Sie neu ist, können Sie die offizielle Dokumentation konsultieren.

In Ihrem Projektverzeichnis sehen Sie nun eine Datei db.sqlite. Diese Datenbank wird unsere Benutzertabelle enthalten.

Schritt 7 — Einrichten der Autorisierungsfunktion

Für unsere Registrierungsfunktion nehmen wir die Daten, die der Benutzer in das Formular eingibt, und und fügen sie unserer Datenbank hinzu. Bevor wir sie hinzufügen, müssen wir sicherstellen, dass der Benutzer nicht bereits in der Datenbank vorhanden ist. Wenn dies nicht der Fall ist, müssen wir sicherstellen, dass wir das Passwort vor dem Hinzufügen in die Datenbank hashen, da wir unsere Passwörter nicht in Klartext speichern möchten.

Beginnen wir mit dem Hinzufügen einer zweiten Funktion zur Verarbeitung der POST-Formulardaten. In dieser Funktion werden wir zuerst die vom Benutzer übergebenen Daten sammeln.

Erstellen Sie die Funktion und fügen Sie ein redirect am Ende hinzu. Dies bietet dem Benutzer die Erfahrung einer erfolgreichen Registrierung und die Weiterleitung zu der Anmeldeseite.

Aktualisieren Sie auth.py durch Ändern der Importzeile und Implementieren von signup_post:

				
					
[label project/auth.py]

from flask import Blueprint, render_template&lt;^&gt;, redirect, url_for&lt;^&gt;

...

@auth.route('/signup', methods=['POST'])

def signup_post():

 # code to validate and add user to database goes here

 return redirect(url_for('auth.login'))

				
			

Fügen wir nun den Rest des Codes hinzu, der für die Registrierung eines Benutzers erforderlich ist.

Zuerst müssen wir das request-Objekt verwenden, um die Formulardaten zu erhalten.

Fahren Sie mit der Aktualisierung von auth.py fort, indem Sie Importe hinzufügen und signup_post implementieren:

				
					
[label auth.py]

from flask import Blueprint, render_template, redirect, url_for&lt;^&gt;, request&lt;^&gt;

from werkzeug.security import generate_password_hash, check_password_hash

from .models import User

from . import db

...

@auth.route('/signup', methods=['POST'])

def signup_post():

 email = request.form.get('email')

 name = request.form.get('name')

 password = request.form.get('password')



 user = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database



 if user: # if a user is found, we want to redirect back to signup page so user can try again

 return redirect(url_for('auth.signup'))



 # create a new user with the form data. Hash the password so the plaintext version isn't saved.

 new_user = User(email=email, name=name, password=generate_password_hash(password, method='sha256'))



 # add the new user to the database

 db.session.add(new_user)

 db.session.commit()



 return redirect(url_for('auth.login'))

				
			

Anmerkung: Das Speichern von Passwörtern in Klartext wird als schlechte Sicherheitspraxis angesehen. In der Regel möchten Sie einen komplexen Hash-Algorithmus und ein Passwort-Salt verwenden, um Passwörter sicher zu halten.

Schritt 8 — Testen der Registrierungsmethode

Nachdem wir nun die Registrierungsmethode abgeschlossen haben, sollten wir in der Lage sein, einen neuen Benutzer zu erstellen. Verwenden Sie das Formular, um einen Benutzer zu erstellen.

Es gibt zwei Möglichkeiten, wie Sie überprüfen können, ob die Registrierung funktioniert: Sie können einen Datenbankbetrachter verwenden, um die Zeile anzuzeigen, die Ihrer Tabelle hinzugefügt wurde, oder Sie können versuchen, sich mit der gleichen E-Mail-Adresse erneut zu registrieren. Wenn Sie einen Fehler erhalten, wissen Sie, dass die erste E-Mail korrekt gespeichert wurde. Lassen Sie uns also diesen Ansatz wählen.

Wir können Code hinzufügen, um dem Benutzer mitzuteilen, dass die E-Mail bereits existiert und ihm sagen, dass er zur Anmeldeseite gehen soll. Durch Aufruf der Funktion flash senden wir eine Nachricht an die nächste Anfrage, die in diesem Fall die Weiterleitung „redirect“ ist. Die Seite, auf der wir landen, wird dann Zugriff auf diese Nachricht in der Vorlage haben.

Zuerst fügen wir die Funktion flash hinzu, bevor wir zurück zu unserer Registrierungsseite umleiten.

				
					
[label project/auth.py]

from flask import Blueprint, render_template, redirect, url_for, request&lt;^&gt;, flash&lt;^&gt;

...

@auth.route('/signup', methods=['POST'])

def signup_post():

 ...

 if user: # if a user is found, we want to redirect back to signup page so user can try again

 flash('Email address already exists')

 return redirect(url_for('auth.signup'))

				
			

Um die geflashte Nachricht in der Vorlage zu erhalten, können wir diesen Code oberhalb des Formulars hinzufügen. Dadurch wird die Nachricht direkt über dem Formular angezeigt.

				
					
[label project/templates/signup.html]

...

{% with messages = get_flashed_messages() %}

{% if messages %}

 &lt;div class="notification is-danger"&gt;

 {{ messages[0] }}. Go to &lt;a href="{{ url_for('auth.login') }}"&gt;login page&lt;/a&gt;.

 &lt;/div&gt;

{% endif %}

{% endwith %}

&lt;form method="POST" action="/signup"&gt;

				
			

Schritt 9 — Hinzufügen der Anmeldemethode

Die Anmeldemethode ähnelt der Registrierungsfunktion insofern, als dass wir die Benutzerinformationen nehmen und etwas damit tun. In diesem Fall vergleichen wir die eingegebene E-Mail-Adresse, um zu sehen, ob sie in der Datenbank enthalten ist. Wenn dies der Fall ist, testen wir das vom Benutzer bereitgestellte Passwort, indem wir das vom Benutzer eingegebene Passwort hashen und es mit dem gehashten Passwort in der Datenbank vergleichen. Wenn beide gehaschten Passwörter übereinstimmen, wissen wir, dass der Benutzer das korrekte Passwort eingegeben hat.

Sobald der Benutzer die Passwort-Überprüfung bestanden hat, wissen wir, dass er die richtigen Anmeldedaten hat und wir können in mit Flask-Login anmelden. Durch den Aufruf von login_user erstellt Flask-Login eine Sitzung für diesen Benutzer, die bestehen bleibt, während der Benutzer angemeldet bleibt, wodurch der Benutzer geschützte Seiten einsehen kann.

Wir können mit einer neuen Route für den Umgang mit den gePOSTeten Dateien beginnen. Wenn sich der Benutzer erfolgreich anmeldet, leiten wir zur Profilseite weiter.

				
					
[label project/auth.py]

...

@auth.route('/login', methods=['POST'])

def login_post():

 # login code goes here

 return redirect(url_for('main.profile'))

				
			

Nun müssen wir überprüfen, ob der Benutzer die richtigen Anmeldedaten hat:

				
					
[label project/auth.py]

...

@auth.route('/login', methods=['POST'])

def login_post():

 email = request.form.get('email')

 password = request.form.get('password')

 remember = True if request.form.get('remember') else False



 user = User.query.filter_by(email=email).first()



 # check if the user actually exists

 # take the user-supplied password, hash it, and compare it to the hashed password in the database

 if not user or not check_password_hash(user.password, password):

 flash('Please check your login details and try again.')

 return redirect(url_for('auth.login')) # if the user doesn't exist or password is wrong, reload the page



 # if the above check passes, then we know the user has the right credentials

 return redirect(url_for('main.profile'))

				
			

Fügen wir den Block in der Vorlage hinzu, damit der Benutzer die geflashte Nachricht sehen kann. Wie bei dem Registrierungsformular fügen wir die potenzielle Fehlermeldung direkt über dem Formular hinzu:

				
					
[label project/templates/login.html]

...

{% with messages = get_flashed_messages() %}

{% if messages %}

 &lt;div class="notification is-danger"&gt;

 {{ messages[0] }}

 &lt;/div&gt;

{% endif %}

{% endwith %}

&lt;form method="POST" action="/login"&gt;

				
			

Wir haben nun die Möglichkeit zu sagen, dass ein Benutzer erfolgreich angemeldet wurde, aber es ist nichts vorhanden, wo der Benutzer protokolliert werden kann. Hier bringen wir Flask-Login zur Verwaltung von Benutzersitzungen ein.

Bevor wir beginnen, benötigen wir einige Dinge, damit Flask-Login funktioniert. Beginnen Sie mit dem Hinzufügen des UserMixin zu Ihrem Benutzermodell. Das UserMixin fügt dem Modell Flask-Login-Attribute hinzu, sodass Flask-Login damit arbeiten kann.

				
					
[label models.py]

from flask_login import UserMixin

from . import db



class User(UserMixin, db.Model):

 id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy

 email = db.Column(db.String(100), unique=True)

 password = db.Column(db.String(100))

 name = db.Column(db.String(1000))

				
			

Dann müssen wir unseren User-Loader angeben. Ein *User-Loader* teilt Flask-Login mit, wie ein bestimmter Benutzer anhand der in seinem Sitzungs-Cookie gespeicherten ID gefunden werden kann. Wir können dies in unserer Funktion create_app zusammen mit dem Code init für Flask-Login hinzufügen:

				
					
[label project/__init__.py]

...

from flask_login import LoginManager

...

def create_app():

 ...

 db.init_app(app)



 login_manager = LoginManager()

 login_manager.login_view = 'auth.login'

 login_manager.init_app(app)



 from .models import User



 @login_manager.user_loader

 def load_user(user_id):

 # since the user_id is just the primary key of our user table, use it in the query for the user

 return User.query.get(int(user_id))

				
			

Schließlich können wir die Funktion login_user hinzufügen, kurz bevor wir auf die Profilseite zur Erstellung der Sitzung weiterleiten:

				
					
[label project/auth.py]

from flask_login import login_user

from .models import User

...

@auth.route('/login', methods=['POST'])

def login_post():

 ...

 # if the above check passes, then we know the user has the right credentials

 login_user(user, remember=remember)

 return redirect(url_for('main.profile'))

				
			

Mit der Einrichtung von Flask-Login können wir die Route /login verwenden. Wenn alles eingerichtet ist, sehen Sie die Profilseite.

Schritt 10 — Schützen von Seiten

Wenn Ihr Name nicht auch Anthony ist, werden Sie feststellen, dass Ihr Name falsch ist. Wir möchten, dass das Profil den Namen in der Datenbank anzeigt. Zuerst müssen wir also die Seite schützen und dann auf die Daten des Benutzers zugreifen, um den Namen zu erhalten.

Um eine Seite bei der Verwendung von Flask-Login zu schützen, fügen wir den Dekorator @login_requried zwischen der Route und der Funktion hinzu. Dadurch wird verhindert, dass ein nicht angemeldeter Benutzer die Route sehen kann. Wenn der Benutzer nicht angemeldet ist, wird der Benutzer gemäß der Flask-Login-Konfiguration auf die Anmeldeseite weitergeleitet.

Bei Routen, die mit dem Dekorator @login_required versehen sind, haben wir dann die Möglichkeit, das Objekt current_user innerhalb der Funktion zu verwenden. Dieser current_user stellt den Benutzer aus der Datenbank dar und wir können mit *der Punktnotation* auf alle Attribute dieses Benutzers zugreifen. Beispielsweise geben current_user.email, current_user.password und current_user.name sowie current_user.id die tatsächlichen Werte zurück, die in der Datenbank für den angemeldeten Benutzer gespeichert sind.

Verwenden wir den Namen des aktuellen Benutzers und senden ihn an die Vorlage. Dann verwenden wir diesen Namen und zeigen seinen Wert an.

				
					
[label project/main.py]

&lt;^&gt;from flask_login import login_required, current_user&lt;^&gt;

...

@main.route('/profile')

@login_required

def profile():

 return &lt;^&gt;render_template('profile.html', name=current_user.name)&lt;^&gt;

				
			

Aktualisieren Sie dann in der Datei profile.html die Seite, um den Wert name anzuzeigen:

				
					
[label project/templates/profile.html]

...

&lt;h1 class="title"&gt;

 Welcome, &lt;^&gt;{{ name }}&lt;^&gt;!

&lt;/h1&gt;

				
			

Sobald wir zu unserer Profilseite gehen, sehen wir, dass der Name des Benutzers angezeigt wird.

Als Letztes können wir die Abmelde-Ansicht aktualisieren. Wir können die Funktion logout_user in einer Route zur Abmeldung aufrufen. Wir haben den Dekorator @login_required, weil es keinen Sinn macht, einen Benutzer abzumelden, der nicht zuerst angemeldet ist.

				
					
[label project/auth.py]

&lt;^&gt;from flask_login import login_user, logout_user, login_required&lt;^&gt;

...

@auth.route('/logout')

@login_required

def logout():

 &lt;^&gt;logout_user()&lt;^&gt;

 return &lt;^&gt;redirect(url_for('main.index'))&lt;^&gt;

				
			

Nachdem wir uns abgemeldet und versucht haben, die Profilseite erneut anzuzeigen, wird eine Fehlermeldung angezeigt. Dies liegt daran, dass Flask-Login eine Nachricht für uns anzeigt, wenn der Benutzer nicht auf eine Seite zugreifen darf.

Eine letzte Sache, die wir tun können, ist, if-Anweisungen in die Vorlage aufzunehmen, um nur die für den Benutzer relevanten Links anzuzeigen. Bevor sich der Benutzer also anmeldet, hat er die Möglichkeit, sich anzumelden oder zu registrieren. Nach der Anmeldung können Benutzer zu ihrem Profil gehen oder sich abmelden:

				
					
[label templates/base.html]

...

&lt;div class="navbar-end"&gt;

 &lt;a href="{{ url_for('main.index') }}" class="navbar-item"&gt;

 Home

 &lt;/a&gt;

 {% if current_user.is_authenticated %}

 &lt;a href="{{ url_for('main.profile') }}" class="navbar-item"&gt;

 Profile

 &lt;/a&gt;

 {% endif %}

 {% if not current_user.is_authenticated %}

 &lt;a href="{{ url_for('auth.login') }}" class="navbar-item"&gt;

 Login

 &lt;/a&gt;

 &lt;a href="{{ url_for('auth.signup') }}" class="navbar-item"&gt;

 Sign Up

 &lt;/a&gt;

 {% endif %}

 {% if current_user.is_authenticated %}

 &lt;a href="{{ url_for('auth.logout') }}" class="navbar-item"&gt;

 Logout

 &lt;/a&gt;

 {% endif %}

&lt;/div&gt;

				
			

Damit haben Sie Ihre Anwendung mit Authentifizierung erfolgreich erstellt.

Zusammenfassung

Wir haben Flask-Login und Flask-SQLAlchemy verwendet, um ein Anmeldesystem für unsere Anwendung zu erstellen. Wir haben behandelt, wie ein Benutzer authentifiziert werden kann, indem wir zuerst ein Benutzermodell erstellen und die Benutzerinformationen speichern. Dann mussten wir verifizieren, dass das Passwort des Benutzers korrekt war, indem wir das Passwort aus dem Formular gehasht und mit dem in der Datenbank gespeicherten Benutzer verglichen haben. Schließlich haben wir unserer Anwendung Autorisierung hinzugefügt, indem wir den Dekorator @login_required auf einer Profilseite verwenden, damit nur angemeldete Benutzer diese Seite sehen können.

Was wir in diesem Tutorial erstellt haben, wird für kleinere Anwendungen ausreichen. Wenn Sie jedoch von Anfang an mehr Funktionalität haben möchten, sollten Sie möglicherweise die Bibliotheken Flask-User oder Flask-Security verwenden, die beide auf der Bibliothek Flask-Login aufbauen.