JSON-Web-Tokens sind einfach zu verwenden und zu debuggen, bieten aber auch einen beeindruckenden Sicherheitsschub.
Eine fehlerhafte Authentifizierung stellt nach wie vor eine anhaltende Schwachstelle in modernen Webanwendungen dar – sie steht nach wie vor ganz oben auf der Liste der zehn größten API-Sicherheitsrisiken von OWASP.
Die Auswirkungen dieser Sicherheitslücke können schwerwiegend sein. Sie können unbefugten Zugriff auf sensible Daten gewähren und die Systemintegrität gefährden. Um den sicheren Zugriff auf Anwendungen und deren Ressourcen effektiv zu gewährleisten, ist es wichtig, dass Sie robuste Authentifizierungsmechanismen verwenden.
Erfahren Sie, wie Sie die Benutzerauthentifizierung in Flask mithilfe von JSON Web Tokens (JWT) implementieren können, einer beliebten und effektiven tokenbasierten Methode.
Tokenbasierte Authentifizierung mit JSON-Web-Tokens
Bei der tokenbasierten Authentifizierung wird eine verschlüsselte Zeichenfolge verwendet, um den Zugriff auf ein System oder eine Ressource zu validieren und zu autorisieren. Sie können diese Art der Authentifizierung mit verschiedenen Methoden implementieren, einschließlich Sitzungstokens, API-Schlüsseln und JSON-Webtokens.
Insbesondere JWTs bieten einen sicheren und kompakten Ansatz für die Übertragung der erforderlichen Benutzeranmeldeinformationen zwischen clientseitigen Anwendungen und Servern.
Ein JWT besteht aus drei Hauptkomponenten: dem Header, der Nutzlast und der Signatur. Der Header enthält Metadaten zum Token, einschließlich des Hashing-Algorithmus, der zum Codieren des Tokens verwendet wird.
Die Nutzlast enthält die tatsächlichen Benutzeranmeldeinformationen, wie z. B. Benutzer-ID und Berechtigungen. Schließlich stellt die Signatur die Gültigkeit des Tokens sicher, indem sie seinen Inhalt mithilfe eines geheimen Schlüssels überprüft.
Mithilfe von JWTs können Sie Benutzer authentifizieren und Sitzungsdaten im Token selbst speichern.
Richten Sie ein Flask-Projekt und eine MongoDB-Datenbank ein
Erstellen Sie zunächst über ein Terminal ein neues Projektverzeichnis:
mkdir flask-projekt
CD-Flaschen-Projekt
Als nächstes installieren virtuelle Umgebung, um eine lokale virtuelle Entwicklungsumgebung für Ihr Flask-Projekt zu erstellen.
virtualenv venv
Aktivieren Sie abschließend die virtuelle Umgebung.
# Unix oder MacOS:
Quelle venv/bin/activate
# Windows:
.\venv\Scripts\activate
Den Code dieses Projekts finden Sie hier GitHub-Repository.
Installieren Sie die erforderlichen Pakete
Erstellen Sie im Stammverzeichnis Ihres Projektordners einen neuen Anforderungen.txt Datei und fügen Sie diese Abhängigkeiten für das Projekt hinzu:
Flasche
pyjwt
python-dotenv
Pymongo
bcrypt
Führen Sie abschließend den folgenden Befehl aus, um die Pakete zu installieren. Stell sicher dass du hast Pip (Paketmanager) installiert; wenn nicht, Installieren Sie es auf Ihrem Windows-, Mac- oder Linux-System.
pip install -r Anforderungen.txt
Erstellen Sie eine MongoDB-Datenbank
Machen Sie weiter und erstellen Sie eine MongoDB-Datenbank. Du kannst Richten Sie eine lokale MongoDB-Datenbank ein, Alternative, Erstellen Sie einen Cluster auf MongoDB Atlas, einem cloudbasierten MongoDB-Dienst.
Nachdem Sie die Datenbank erstellt haben, kopieren Sie den Verbindungs-URI und erstellen Sie eine .env Datei im Stammverzeichnis Ihres Projekts und fügen Sie sie wie folgt hinzu:
MONGO_URI=""
Konfigurieren Sie abschließend die Datenbankverbindung über Ihre Flask-Anwendung. Erstelle eine neue utils/db.py Datei im Stammverzeichnis Ihres Projekts mit diesem Code:
aus Pymongo importieren MongoClient
defconnect_to_mongodb(mongo_uri):
client = MongoClient (mongo_uri)
db = client.get_database(„Benutzer“)
zurückkehren db
Diese Funktion stellt mithilfe des bereitgestellten Verbindungs-URI eine Verbindung zur MongoDB-Datenbank her. Es entsteht dann ein neues Benutzer Sammlung, wenn sie nicht existiert, und gibt die entsprechende Datenbankinstanz zurück.
Erstellen Sie den Flask-Webserver
Wenn die Datenbank konfiguriert ist, erstellen Sie eine app.py Datei im Stammverzeichnis des Projektordners und fügen Sie den folgenden Code hinzu, um eine Instanz der Flask-Anwendung zu erstellen.
aus Flasche importieren Flasche
aus Routen.user_auth importieren register_routes
aus utils.db importieren connect_to_mongodb
importieren os
aus dotenv importieren load_dotenvapp = Flasche (__name__)
load_dotenv()mongo_uri = os.getenv('MONGO_URI')
db = connect_to_mongodb (mongo_uri)register_routes (App, Datenbank)
Wenn __name__ == '__hauptsächlich__':
app.run (debug=WAHR)
Erstellen Sie die Authentifizierungs-API-Endpunkte
Um die Benutzerauthentifizierung in Ihrer Flask-Anwendung zu implementieren, ist es wichtig, die erforderlichen API-Endpunkte zu definieren, die authentifizierungsbezogene Vorgänge verarbeiten.
Definieren Sie jedoch zunächst das Modell für die Daten der Benutzer. Erstellen Sie dazu ein neues model/user_model.py Datei im Stammverzeichnis und fügen Sie den folgenden Code hinzu.
aus pymongo.collection importieren Sammlung
aus bson.objectid importieren Objekt IdentifikationKlasseBenutzer:
def__drin__(selbst, Sammlung: Sammlung, Benutzername: str, Passwort: str):
self.collection = Sammlung
self.username = Benutzername
self.password = Passwort
defspeichern(selbst):
user_data = {
'Nutzername': self.username,
'Passwort': Selbstpasswort
}
result = self.collection.insert_one (user_data)
zurückkehren str (result.inserted_id)@staticmethod
deffind_by_id(Sammlung: Sammlung, Benutzer-ID: str):
zurückkehren Sammlung.find_one({'_Ausweis': ObjectId (user_id)})
@staticmethod
deffind_by_username(Sammlung: Sammlung, Benutzername: str):
zurückkehren Sammlung.find_one({'Nutzername': Nutzername})
Der obige Code gibt a an Benutzer Klasse, die als Datenmodell dient und mehrere Methoden für die Interaktion mit einer MongoDB-Sammlung definiert, um benutzerbezogene Vorgänge auszuführen.
- Der speichern Die Methode speichert ein neues Benutzerdokument mit dem angegebenen Benutzernamen und Passwort in der MongoDB-Sammlung und gibt die ID des eingefügten Dokuments zurück.
- Der find_by_id Und find_by_username Methoden rufen Benutzerdokumente aus der Sammlung basierend auf der bereitgestellten Benutzer-ID bzw. dem Benutzernamen ab.
Definieren Sie die Authentifizierungsrouten
- Beginnen wir mit der Definition der Registrierungsroute. Diese Route fügt der MongoDB-Benutzersammlung neue Benutzerdaten hinzu. Erstellen Sie im Stammverzeichnis ein neues Routen/user_auth.py Datei und den folgenden Code.
importieren jwt
aus Funktionstools importieren wickelt
aus Flasche importieren jsonify, request, make_response
aus models.user_model importieren Benutzer
importieren bcrypt
importieren osdefregister_routes(App, Datenbank):
Sammlung = db.users
app.config['GEHEIMER SCHLÜSSEL'] = os.urandom(24)@app.route('/api/register', method=['POST'])
defregistrieren():
Benutzername = request.json.get('Nutzername')
Passwort = request.json.get('Passwort')
bestehender_user = User.find_by_username (Sammlung, Benutzername)
Wenn existierender Benutzer:
zurückkehren jsonify({'Nachricht': 'Benutzername existiert bereits!'})
hasshed_password = bcrypt.hashpw (password.encode('utf-8'), bcrypt.gensalt())
new_user = Benutzer (Sammlung, Benutzername, hashed_password.decode('utf-8'))
user_id = new_user.save()zurückkehren jsonify({'Nachricht': „Benutzer erfolgreich registriert!“, 'Benutzer-ID': Benutzer-ID})
- Implementieren Sie die Anmeldefunktion, um den Authentifizierungsprozess abzuwickeln und die Benutzeranmeldeinformationen zu überprüfen. Fügen Sie unter der Registrierungsroute den folgenden Code hinzu.
Der Anmeldeendpunkt führt zwei Dinge aus: Er überprüft die angegebenen Benutzeranmeldeinformationen und generiert nach erfolgreicher Authentifizierung ein eindeutiges JWT für diesen Benutzer. Es legt dieses Token als Cookie in der Antwort fest, zusammen mit einer JSON-Nutzlast, die eine erfolgreiche Anmeldung anzeigt. Wenn die Anmeldeinformationen ungültig sind, wird eine JSON-Antwort zurückgegeben, um dies anzuzeigen.@app.route('/api/login', Methoden=['POST'])
defAnmeldung():
Benutzername = request.json.get('Nutzername')
Passwort = request.json.get('Passwort')
user = User.find_by_username (Sammlung, Benutzername)
Wenn Benutzer:
Wenn bcrypt.checkpw (password.encode('utf-8'), Benutzer['Passwort'].kodieren('utf-8')):
token = jwt.encode({'Benutzer-ID': str (Benutzer['_Ausweis'])}, app.config['GEHEIMER SCHLÜSSEL'], Algorithmus='HS256')
Antwort = make_response (jsonify({'Nachricht': 'Anmeldung erfolgreich!'}))
Antwort.set_cookie('Zeichen', Zeichen)
zurückkehren Antwortzurückkehren jsonify({'Nachricht': 'Ungültiger Benutzername oder Passwort'})
- Definieren Sie eine Dekoratorfunktion, die die JSON-Web-Tokens (JWTs) überprüft, die zusammen mit nachfolgenden API-Anfragen übergeben werden. Fügen Sie den folgenden Code innerhalb des hinzu register_routes Funktionscodeblock.
Diese Dekoratorfunktion stellt das Vorhandensein eines gültigen JWT-Tokens in nachfolgenden API-Anfragen sicher. Es prüft, ob das Token fehlt, abgelaufen oder gültig ist, und gibt gegebenenfalls eine entsprechende JSON-Antwort zurück.deftoken_required(F):
@wraps (f)
defdekoriert(*args, **kwargs):
token = request.cookies.get('Zeichen')Wennnicht Zeichen:
zurückkehren jsonify({'Nachricht': „Token fehlt!“}), 401versuchen:
data = jwt.decode (token, app.config['GEHEIMER SCHLÜSSEL'], Algorithmen=['HS256'])
current_user = User.find_by_id (Sammlung, Daten['Benutzer-ID'])
außer jwt. ExpiredSignatureError:
zurückkehren jsonify({'Nachricht': „Token ist abgelaufen!“}), 401
außer jwt. InvalidTokenError:
zurückkehren jsonify({'Nachricht': „Ungültiges Token!“}), 401zurückkehren f (aktueller_Benutzer, *args, **kwargs)
zurückkehren dekoriert
- Erstellen Sie abschließend eine geschützte Route.
@app.route('/api/users', method=['GET'])
@token_required
defget_users(aktueller_Benutzer):
Benutzer = Liste (collection.find({}, {'_Ausweis': 0}))
zurückkehren jsonify (Benutzer)
Dieser Endpunkt verwaltet die Logik zum Abrufen von Benutzerdaten aus der Datenbank, erfordert jedoch, dass der Client, der Anfragen sendet, ein gültiges Token für den Zugriff auf die Daten enthält.
Führen Sie abschließend den folgenden Befehl aus, um den Entwicklungsserver hochzufahren.
Kolbenlauf
Um die Registrierung, Anmeldung und den Endpunkt der geschützten Benutzer zu testen, können Sie Postman oder einen anderen API-Client verwenden. Senden Sie Anfragen an http://localhost: 5000/api/und beobachten Sie die Antworten, um die Funktionalität dieser API-Endpunkte zu überprüfen.
Ist die Token-Authentifizierung eine narrensichere Sicherheitsmaßnahme?
JSON-Web-Tokens bieten eine robuste und effektive Möglichkeit zur Authentifizierung von Benutzern für Ihre Web-App. Es ist jedoch wichtig zu verstehen, dass die Token-Authentifizierung nicht narrensicher ist; Es ist nur ein Teil eines größeren Sicherheitspuzzles.
Kombinieren Sie die Token-Authentifizierung mit anderen Best Practices für die Sicherheit. Denken Sie daran, kontinuierlich zu überwachen und einheitliche Sicherheitspraktiken anzuwenden; Sie erhöhen die Gesamtsicherheit Ihrer Flask-Anwendungen erheblich.