Erfahren Sie, wie Sie eine REST-API mit JSON-Web-Token sichern, um zu verhindern, dass Benutzer und Anwendungen von Drittanbietern sie missbrauchen.
Wir werden einen Datenbankdienst mit erstellen SQLite und Benutzern den Zugriff über eine REST-API mithilfe von HTTP-Methoden wie POST und PUT ermöglichen.
Darüber hinaus erfahren wir, warum JSON-Web-Token eine geeignete Methode zum Schutz der Rest-API anstelle von Digest und Basisauthentifizierung sind. Bevor wir fortfahren, wollen wir den Begriff JSON-Web-Token, REST-API und Flask-Framework verstehen.
JSON-Web-Token
JSON-Web-Token, auch bekannt als JWTist die sichere Möglichkeit, zufällige Token zwischen zwei Parteien oder Entitäten zu übertragen. JSON besteht normalerweise aus drei Teilen:
- Nutzlast: XNUMX Kg
- Kopfzeile
- Signature
JSON verwendet zwei Arten von Strukturformularen, wenn Daten oder Informationen zwischen zwei Parteien übertragen werden.
- Serialisiert
- Deserialisiert
Das serialisierte Formular wird verwendet, wenn Daten über jede Anforderung und Antwort an das Netzwerk übertragen werden, während das deserialisierte Formular beim Lesen und Schreiben von Daten in das Web-Token verwendet wird.
In der serialisierten Form gibt es drei Komponenten.
- Kopfzeile
- Nutzlast: XNUMX Kg
- Signature
Die Header-Komponente definiert die kryptografischen Informationen zu den Token. Beispielsweise:
- Ist es signiert oder unsigniert JWT?
- Definieren Sie Algorithmus-Techniken
Die deserialisierte Form enthält im Gegensatz zur serialisierten Form zwei Komponenten.
- Nutzlast: XNUMX Kg
- Kopfzeile
REST API
API (Application Programming Interface) ermöglicht die Kommunikation zwischen zwei Anwendungen, um die Daten abzurufen oder zu senden. Es gibt zwei beliebte Arten von APIs - Web- und System-APIs.
In diesem Artikel werden wir uns nur mit der Web-API befassen. Es gibt zwei Arten von Web-APIs.
- Request-Response-API: Rest, GraphQL, Remote Procedure Call (RPC)
- Ereignisgesteuerte API: WebHooks, Web Sockets, HTTP-Streaming
Die REST-API fällt unter die Kategorie Anfrage-Antwort. Es verwendet HTTP-Methoden wie GET, POST und PUT, um API-Operationen auszuführen.
Ein klassisches Beispiel ist, wenn ein Benutzer eine GET-Methode an den Webdienst sendet, um eine bestimmte Ressource oder eine Sammlung von Ressourcen anzufordern oder abzurufen. Der Server sendet dann die spezifische Ressource oder Sammlung von Ressourcen an den Benutzer zurück, der sie angefordert hat.
Kolben-Framework
Flask ist ein Framework, das auf Python basiert. Es ist ein Mikro-Framework, das von Python-Entwicklern zum Erstellen der Rest-API verwendet wird. Es wird als Micro-Framework bezeichnet, da Entwickler beispielsweise benutzerdefinierte Authentifizierung und jedes andere Backend-System basierend auf den Einstellungen hinzufügen können.
Beginnen wir mit der Implementierung. Mein System-Setup ist wie folgt.
- Ubuntu als Betriebssystem
- Python 2.7 +
- Postman
Richten Sie mit virtualenv eine virtuelle Umgebung ein
Wir müssen eine virtuelle Umgebung einrichten, um sicherzustellen, dass einige Pakete nicht mit Systempaketen in Konflikt stehen. Verwenden wir die virtualenv
um eine neue virtuelle Umgebung einzurichten.
Vorausgesetzt, Sie haben die pip
Führen Sie den folgenden Befehl über aus, der auf Ihrem System verfügbar ist pip
installieren.
pip install virtualenv
Wenn Sie keinen Pip auf Ihrer Maschine haben, befolgen Sie diese Anweisungen Dokumentation um pip auf Ihrem System zu installieren.
Als Nächstes erstellen wir ein Verzeichnis zum Speichern oder Speichern unserer virtuellen Umgebung. Verwenden Sie die mkdir
Befehl unten gezeigt, um ein Verzeichnis zu erstellen
mkdir flaskproject
Wechseln Sie in die flaskproject
Verzeichnis mit dem folgenden Befehl
cd flaskproject
Im Inneren der flaskproject
Verzeichnis verwenden Sie die virtualenv
Tool zum Erstellen einer virtuellen Umgebung wie unten gezeigt:
virtualenv flaskapi
Nachdem Sie die verwendet haben virtualenv
Führen Sie das Tool zum Erstellen der virtuellen Umgebung aus cd
Befehl zum Wechseln in die flaskapi
Verzeichnis als virtuelle Umgebung und aktivieren Sie es mit dem folgenden Befehl.
source bin/activate
Führen Sie alle mit diesem Projekt verbundenen Aufgaben in der virtuellen Umgebung aus.
Installieren Sie Pakete mit pip
Jetzt ist es Zeit, Pakete wie das Flask Framework und PyJWT zu installieren, mit denen wir die Rest-API und andere notwendige Pakete für unser API-Projekt erstellen.
Erstellen Sie requirements.txt
Datei mit den folgenden Paketen.
Flask
datetime
uuid
Flask-SQLAlchemy
PyJWT
Installieren Sie sie mit pip.
pip install -r requirements.txt
Richten Sie eine Datenbank ein
Lassen Sie uns SQLite installieren.
apt-get install sqlite3
Erstellen Sie eine Datenbank mit dem Namen Bibliothek. In dieser Datenbank erstellen wir zwei Tabellen, nämlich die Users
und Authors
Tabelle.
Die Benutzertabelle enthält registrierte Benutzer. Nur registrierte Benutzer können auf die Authors-Tabelle zugreifen.
In der Autorentabelle werden die Informationen oder Details der Autoren gespeichert, z. B. der Name des Autors, das Geburtsland usw., die von den registrierten Benutzern übermittelt wurden.
Erstellen Sie die Datenbank mit dem folgenden Befehl:
sqlite3 library.db
Mit dem folgenden Befehl können Sie überprüfen, ob Sie die Datenbank erfolgreich erstellt haben:
.databases
Öffnen Sie ein neues Terminal und führen Sie Folgendes in der zuvor erstellten virtuellen Umgebung aus.
touch app.py
Fügen Sie den folgenden Code in die genannte Datei ein app.py
from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
import uuid
import jwt
import datetime
from functools import wraps
Die erste Zeile im obigen Code importiert Pakete wie request
und jsonify
. Wir werden davon Gebrauch machen request
Verfolgen der Daten auf Anforderungsebene während einer Anforderung und Verwendung jsonify
Antworten in a ausgeben JSON Format.
In der nächsten Zeile haben wir SQLAlchemy aus importiert flask_sqlalchemy
um SQLAlchemy-Funktionen in den Kolben zu integrieren.
Von werkzeug.security
haben wir importiert generate_password_hash
um Passwort-Hash für Benutzer und zu generieren check_password_hash
um das Kennwort des Benutzers zu überprüfen, wenn das von Benutzern übermittelte Kennwort mit den in der Datenbank gespeicherten Kennwörtern des Benutzers verglichen wird.
Schließlich haben wir importiert uuid
Wird auch als universelle eindeutige Kennung bezeichnet, um zufällige ID-Nummern für Benutzer zu generieren.
Trotzdem in der app.py
Implementieren Sie die Konfigurationseinstellungen für die Bibliotheks-API mithilfe des folgenden Codes in der Datei app.py.
Platzieren Sie den folgenden Code unter der Importanweisung.
app = Flask(__name__)
app.config['SECRET_KEY']='Th1s1ss3cr3t'
app.config['SQLALCHEMY_DATABASE_URI']='sqlite://///home/michael/geekdemos/geekapp/library.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
Erstellen Sie nun zwei Modelle für die Tabelle Benutzer und Autoren, wie unten gezeigt. Kopieren Sie den Code und fügen Sie ihn in die Datei app.py ein.
Platzieren Sie den Code unten rechts unter dieser Datenbankeinstellung db = SQLAlchemy(app)
class Users(db.Model):
id = db.Column(db.Integer, primary_key=True)
public_id = db.Column(db.Integer)
name = db.Column(db.String(50))
password = db.Column(db.String(50))
admin = db.Column(db.Boolean)
class Authors(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), unique=True, nullable=False))
book = db.Column(db.String(20), unique=True, nullable=False))
country = db.Column(db.String(50), nullable=False))
booker_prize = db.Column(db.Boolean)
Generieren Sie Benutzer- und Autorentabellen
Geben Sie auf dem Terminal den folgenden Code in die virtuelle Umgebung ein, um Tabellen für die Tabellen Benutzer und Autoren zu generieren oder zu erstellen, wie unten gezeigt
from app import db
db.create_all()
Öffnen Sie anschließend die app.py
Datei in der virtuellen Umgebung und erstellen Sie eine andere Funktion.
Diese Funktion generiert Token, damit nur registrierte Benutzer auf eine Reihe von API-Vorgängen für die Authors-Tabelle zugreifen und diese ausführen können.
Platzieren Sie diesen Code unter dem Datenbankmodell für die Autorentabelle
def token_required(f):
@wraps(f)
def decorator(*args, **kwargs):
token = None
if 'x-access-tokens' in request.headers:
token = request.headers['x-access-tokens']
if not token:
return jsonify({'message': 'a valid token is missing'})
try:
data = jwt.decode(token, app.config[SECRET_KEY])
current_user = Users.query.filter_by(public_id=data['public_id']).first()
except:
return jsonify({'message': 'token is invalid'})
return f(current_user, *args, **kwargs)
return decorator
Erstellen Sie Routen für die Benutzertabelle
Erstellen wir nun eine Route, über die sich Benutzer über einen Benutzernamen und ein Kennwort wie unten gezeigt für die Autoren-API registrieren können.
Öffnen Sie wieder die app.py
Datei in der virtuellen Umgebung und fügen Sie den folgenden Code unter der Funktion ein token_required(f)
@app.route('/register', methods=['GET', 'POST'])
def signup_user():
data = request.get_json()
hashed_password = generate_password_hash(data['password'], method='sha256')
new_user = Users(public_id=str(uuid.uuid4()), name=data['name'], password=hashed_password, admin=False)
db.session.add(new_user)
db.session.commit()
return jsonify({'message': 'registered successfully'})
Erstellen Sie in der virtuellen Umgebung eine andere Route in der app.py
Datei, damit sich registrierte Benutzer anmelden können.
Wenn sich ein Benutzer anmeldet, wird ein zufälliges Token generiert, damit der Benutzer auf die Bibliotheks-API zugreifen kann.
Fügen Sie den folgenden Code unter die zuvor erstellte Route ein.
@app.route('/login', methods=['GET', 'POST'])
def login_user():
auth = request.authorization
if not auth or not auth.username or not auth.password:
return make_response('could not verify', 401, {'WWW.Authentication': 'Basic realm: "login required"'})
user = Users.query.filter_by(name=auth.username).first()
if check_password_hash(user.password, auth.password):
token = jwt.encode({'public_id': user.public_id, 'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=30)}, app.config['SECRET_KEY'])
return jsonify({'token' : token.decode('UTF-8')})
return make_response('could not verify', 401, {'WWW.Authentication': 'Basic realm: "login required"'})
Erstellen Sie in der virtuellen Umgebung dennoch eine andere Route in der app.py
Datei, um alle registrierten Benutzer abzurufen oder abzurufen.
Dieser Code sucht nach allen registrierten Benutzern in der Benutzertabelle und gibt das Endergebnis in einem JSON-Format zurück.
Fügen Sie den folgenden Code unter die Anmelderoute ein
@app.route('/users', methods=['GET'])
def get_all_users():
users = Users.query.all()
result = []
for user in users:
user_data = {}
user_data['public_id'] = user.public_id
user_data['name'] = user.name
user_data['password'] = user.password
user_data['admin'] = user.admin
result.append(user_data)
return jsonify({'users': result})
Erstellen Sie Routen für die Autorentabelle
Erstellen Sie Routen für die Authors-Tabelle, damit Benutzer alle Autoren in der Datenbank abrufen und Autoren löschen können.
Nur Benutzer mit gültigen Token können diese API-Vorgänge ausführen.
Erstellen Sie in der Datei app.py eine Route für registrierte Benutzer, um neue Autoren zu erstellen.
Fügen Sie diesen Code unter die Route ein, damit ein Benutzer alle registrierten Benutzer abrufen kann.
@app.route('/author', methods=['POST', 'GET'])
@token_required
def create_author(current_user):
data = request.get_json()
new_authors = Authors(name=data['name'], country=data['country'], book=data['book'], booker_prize=True, user_id=current_user.id)
db.session.add(new_authors)
db.session.commit()
return jsonify({'message' : 'new author created'})
Erstellen Sie als Nächstes eine andere Route, damit ein registrierter Benutzer mit einem gültigen Token alle Autoren in der Autorentabelle abrufen kann (siehe unten).
Fügen Sie diesen Code unterhalb der Route ein, damit ein Benutzer einen neuen Autor erstellen kann.
@app.route('/authors', methods=['POST', 'GET']) @token_required def get_authors(current_user): authors = Authors.query.filter_by(user_id=current_user.id).all() output = [] for author in authors: author_data = {} author_data['name'] = author.name author_data['book'] = author.book author_data['country'] = author.country author_data['booker_prize'] = author.booker_prize output.append(author_data) return jsonify({'list_of_authors' : output})
Endlich noch im app.py
Erstellen Sie eine Route, um einen angegebenen Autor zu löschen, wie unten gezeigt.
Fügen Sie diesen Code unter die Route ein, damit ein Benutzer eine Liste der Autoren abrufen kann.
@app.route('/authors/<author_id>', methods=['DELETE'])
@token_required
def delete_author(current_user, author_id):
author = Author.query.filter_by(id=author_id, user_id=current_user.id).first()
if not author:
return jsonify({'message': 'author does not exist'})
db.session.delete(author)
db.session.commit()
return jsonify({'message': 'Author deleted'})
if __name__ == '__main__':
app.run(debug=True)
Speichern und schließen Sie anschließend die Datei app.py in der virtuellen Umgebung.
Testing the library API with Postman
In diesem Abschnitt verwenden wir ein Postboten-Tool, um eine Anfrage an die Datenbankdienste zu senden. Wenn Sie keinen Postboten auf Ihrem Computer haben, können Sie herausfinden, wie Sie ihn herunterladen und installieren können hier .
Neben dem Postboten können wir auch andere Tools wie z Curl um Anfragen an den Server zu senden.
Öffnen Sie ein neues Terminal und geben Sie Folgendes ein:
postman
Der Befehl postman
Ihr Webbrowser zeigt die folgende Seite an:
Sie können sich entscheiden, sich anzumelden und ein kostenloses Konto zu erstellen. Wir werden jedoch überspringen und direkten Zugriff auf die App erhalten, um die Bibliotheks-API wie unten gezeigt zu testen:
In diesem Abschnitt können Benutzer sich für die Bibliotheks-API registrieren, indem sie mithilfe der POST-Methode einen Benutzernamen und ein eindeutiges Kennwort in einem JSON-Format mithilfe der folgenden Schritte angeben:
- Klicken Sie auf die Registerkarte Body
- Wählen Sie dann die Rohschaltfläche und das JSON-Format
- Geben Sie einen Benutzernamen und ein Passwort ein, um sich wie im Screenshot gezeigt zu registrieren
- Geben Sie neben der Schaltfläche "Senden" die folgende URL ein: http://127.0.0.1/register
- Ändern Sie abschließend die Methode in POST und drücken Sie die Senden-Taste.
Die folgende Ausgabe wird wie folgt angezeigt:
Jetzt haben wir erfolgreich einen Benutzer registriert. Lassen Sie uns fortfahren, damit der Benutzer, der sich gerade registriert hat, sich anmelden kann, um ein temporäres zufälliges Token zu generieren, und mit den folgenden Schritten auf die Authors-Tabelle zugreifen kann:
- Klicken Sie auf die Registerkarte Autorisierung.
- Wählen Sie im Abschnitt Typ die Standardauthentifizierung aus.
- Füllen Sie dann das Formular für Benutzername und Passwort mit dem Benutzernamen und Passwort aus, mit dem Sie sich zuvor registriert haben.
- Drücken Sie abschließend die Senden-Taste, um sich anzumelden und ein zufälliges Token zu generieren.
Sobald sich der Benutzer erfolgreich angemeldet hat, wird ein zufälliges Token für den Benutzer generiert, wie im Screenshot gezeigt.
Wir werden das generierte zufällige Token verwenden, um auf die Authors-Tabelle zuzugreifen.
In diesem Abschnitt fügen wir der Autorentabelle über die POST-Methode die Informationen eines Autors hinzu, indem wir die folgenden Schritte ausführen:
- Klicken Sie auf die Registerkarte Überschriften
- Fügen Sie die folgenden im Screenshot gezeigten HTTP-Header ein
- Klicken Sie anschließend auf die Registerkarte "Text" und geben Sie die Details des neuen Autors ein
- Drücken Sie dann die Senden-Taste, um die Details des Autors zur Tabelle des Autors hinzuzufügen
Sie können die Informationen der Autoren in der Autorentabelle auch über Folgendes abrufen:
- Stellen Sie sicher, dass sich Ihr generiertes Token im Abschnitt Header befindet. Wenn es nicht vorhanden ist, müssen Sie es mit Ihrem Token füllen.
- Geben Sie neben der Schaltfläche Senden diese URL ein
http://127.0.0.1/authors
- Ändern Sie dann die HTTP-Methode in GET und drücken Sie die Senden-Taste, um die Details des Autors abzurufen.
Schließlich können Sie die Autoren in der Autorentabelle über das löschen DELETE
Methode mit den folgenden Schritten:
- Stellen Sie sicher, dass sich Ihr Token noch im Header-Bereich befindet. Sie können die Registerkarte Überschriften überprüfen, um sicherzustellen, dass die erforderlichen Informationen vorhanden sind.
- Geben Sie neben der Schaltfläche Senden diese URL ein
http://127.0.0.1/sam
- Drücken Sie dann die Senden-Taste, um den von Ihnen angegebenen Benutzer zu löschen.
Den vollständigen Quellcode finden Sie unter Github. Sie können es klonen und auf Ihrem Computer auschecken.