Tangerine-Auth ist eine Python-Bibliothek, die Dienstprogramme für die Benutzerauthentifizierung und die sichere Handhabung von Schlüssel und verschlüsselten Daten bietet. Es verwendet BCrypt für Passwort Hashing und JWT für tokenbasierte Authentifizierung.
Hinweis: Tangerine-Auth ist derzeit in Beta. Es wird noch nicht nur für die Produktionsverwendung empfohlen. Bitte zögern Sie nicht, in der Zwischenzeit damit herunterzuladen und damit herumzuspielen! Wir arbeiten daran, weitere Tests und Dokumentation hinzuzufügen. Wenn Sie Fehler finden oder Vorschläge haben, öffnen Sie bitte ein Problem auf GitHub.
Verwenden Sie PIP, um das Paket zu installieren:
pip install tangerine-authDie allgemeinen Schritte zur Integration von Yuzu in Ihre Anwendung sind wie folgt:
def get_user_by_email ( email ):
conn = psycopg2 . connect ( "postgresql://postgres:<your postgres password>@localhost:5432/local_development" )
cur = conn . cursor ()
cur . execute ( "SELECT * FROM tangerine.users WHERE email = %s" , ( email ,))
user = cur . fetchone ()
cur . close ()
conn . close ()
if user :
return { '_id' : user [ 0 ], 'email' : user [ 1 ], 'password' : user [ 2 ]}
else :
return None
def create_user ( user_data ):
conn = psycopg2 . connect ( "postgresql://<your postgres password>@localhost:5432/local_development" )
cur = conn . cursor ()
cur . execute ( "INSERT INTO tangerine.users (email, password) VALUES (%s, %s) RETURNING id" , ( user_data [ 'email' ], user_data [ 'password' ]))
user_id = cur . fetchone ()[ 0 ]
conn . commit ()
cur . close ()
conn . close ()
return { '_id' : user_id , 'email' : user_data [ 'email' ], 'password' : user_data [ 'password' ]}Erstellen Sie ein Keylime -Objekt und geben Sie es an den Yuzu -Konstruktor weiter. Das Keylime -Objekt wird zum sicheren Umgang mit Schlüssel und verschlüsselten Daten verwendet. Sie können das Keylime -Objekt verwenden, um Daten zu verschlüsseln und zu entschlüsseln und Schlüssel zu speichern und abzurufen.
Erstellen Sie ein Yuzu -Objekt und übergeben Sie es das Keylime -Objekt, die Funktion zum Auffinden eines Benutzers in Ihrer Datenbank und die Funktion zum Erstellen eines Benutzers in Ihrer Datenbank.
(Optional) Yuzu verwendet Bcrypt, um Hash -Passwörter zu erhalten. Sie können optional eine benutzerdefinierte Hash -Funktion an den Yuzu -Konstruktor übergeben. Die benutzerdefinierte Hash -Funktion sollte eine Kennwortzeichenfolge als Argument aufnehmen und eine Hash -Kennwort -Zeichenfolge zurückgeben.
Nachdem Schritt 3 abgeschlossen ist, können Sie jetzt das Yuzu -Objekt verwenden, um einen neuen Benutzer anzumelden, sich bei einem Benutzer anzumelden, einen Benutzer anzumelden und Authentifizierungs -Token zu überprüfen.
Yuzu wurde gebaut, um sowohl mit Flask als auch mit Mandarine zu arbeiten. Derzeit sind zwei JWT Middlewares mit Yuzu, einen für Flask und eine für Mandarine gebündelt. Sobald Sie die Yuzu -Klasse ordnungsgemäß initialisiert haben, können Sie die Mandarine Middleware unterrufen:
app . use ( auth . jwt_middleware ).Die Flask-Version JWT Middleware ist immer noch experimentell und könnte zu Problemen sein. Es wird erst für den Produktionsgebrauch empfohlen, bis es gründlicher getestet wurde. Die JWT Middleware funktioniert im Flaschen etwas anders, um sie mit Flask zu verwenden. Sie verwenden sie als Dekorateur:
from flask import Flask
from yuzu import Yuzu
app = Flask ( __name__ )
def get_user_by_email ( email ):
# Logic to create user in DB
pass
def create_user ( user_data ):
# Logic to create user in DB
pass
auth = Yuzu ( keychain , get_user_by_email , create_user ) # Fill with your functions
@ app . route ( '/secure_route' )
@ auth . flask_jwt_middleware ( auth )
def secure_route ():
# Your secure code here. This will only run if the JWT is valid.
return "This is a secure route"
if __name__ == "__main__" :
app . run ( debug = True )Hinweis: Die Auth -Middleware findet die Benutzerdaten an das CTX -Objekt an. Sie können auf die Benutzerdaten in Ihrem Routenhandler zugreifen
ctx . auth . user or ctx . get ( "user" )Yuzu ist eine Klasse, die Benutzerauthentifizierungsfunktionen bietet. Es verwendet BCrypt für Passwort Hashing und JWT zum Erstellen und Überprüfen von Authentifizierungs -Token.
Im Folgenden finden Sie die Schlüsselmethoden der Yuzu -Klasse:
- `__init__(self, keychain, get_user_by_email, create_user, hash_func: Optional[Callable] = None)` : Initializes the Yuzu object .
- `get_config(self, key_name: str) -> str` : Fetches the configuration value for a given key .
- `authenticate(self, email: str, password: str) -> bool` : Checks if the given email and password are valid .
- `generate_auth_token(self, user_id: str, email: str) -> str` : Generates an authentication token for the given user .
- `verify_auth_token(self, token: str) -> dict` : Verifies if the given authentication token is valid .
- `sign_up(self, user_data: dict) -> dict` : Signs up a new user with the given user data .
- `login(self, email: str, password: str) -> Tuple[str, str]` : Logs in a user with the given email and password .
- `logout(self)` : Logs out the current user .
- `jwt_middleware()` : Tangerine middleware for JWT authentication .
- `flask_jwt_middleware(yuzu_instance)` : Flask middleware for JWT authentication .Keylime ist eine Klasse, die Funktionen für sichere Handhabung von Schlüssel und verschlüsselten Daten bietet.
Im Folgenden finden Sie die Schlüsselmethoden der Keylime -Klasse:
- `__init__(self, keychain: Dict[str, bytes] = {})` : Initializes the KeyLime object .
- `add_key(self, key_name: str, key: bytes)` : Adds a key to the keychain .
- `remove_key(self, key_name: str)` : Removes a key from the keychain .
- `get_key(self, key_name: str) -> bytes` : Fetches a key from the keychain .
- `encrypt(self, key_name: str, message: str) -> str` : Encrypts a given message using a key from the keychain .
- `decrypt(self, key_name: str, cipher_text: str) -> str` : Decrypts a given cipher text using a key from the keychain .Das allgemeine Conept dafür ist, dass Sie zwei Funktionen schreiben möchten, einen zum Auffinden eines Benutzers in Ihrem ausgewählten Datenbanksystem und eines, um einen Benutzer in Ihrem ausgewählten Datenbanksystem zu erstellen. Diese Funktionen sollten ein Wörterbuch von Benutzerdaten als Argument aufnehmen und ein Wörterbuch der Benutzerdaten zurückgeben. Das Benutzerdaten -Wörterbuch sollte mindestens ein E -Mail- und Kennwort enthalten. Das Benutzerdatenwörterbuch kann alle anderen Felder enthalten, die Sie in Ihrer Datenbank speichern möchten.
Hier ist ein Beispiel für die Verwendung der Yuzu- und Keylime -Klassen:
from tangerine import Tangerine , Ctx , Router
from pymongo import MongoClient
from tangerine . key_lime import KeyLime
from tangerine . yuzu import Yuzu
import json
import jwt
import hashlib
app = Tangerine ( debug_level = 1 )
client = MongoClient ( 'mongodb://localhost:27017/' )
keychain = KeyLime ({
"SECRET_KEY" : "ILOVECATS" ,
})
def get_user_by_email ( email ):
db = client [ 'mydatabase' ]
users = db [ 'users' ]
query = { 'email' : email }
user = users . find_one ( query )
if user :
user [ '_id' ] = str ( user [ '_id' ]) # Convert ObjectId to string
return user
def create_user ( user_data ):
db = client [ 'mydatabase' ]
users = db [ 'users' ]
result = users . insert_one ( user_data )
if result . inserted_id :
user_data [ '_id' ] = str ( result . inserted_id ) # Convert ObjectId to string
return user_data
auth = Yuzu ( keychain , get_user_by_email , create_user )
# serve static files to any request not starting with /api
app . static ( '^/(?!api).*$' , './public' )
# This is how you define a custom middleware.
def hello_middle ( ctx : Ctx , next ) -> None :
ctx . hello_message = json . dumps ({ "message" : "Hello from middleware!" })
next ()
# ==================== AUTH HANDLERS ====================
def api_hello_world ( ctx : Ctx ) -> None :
ctx . body = ctx . hello_message
ctx . send ( 200 , content_type = 'application/json' )
def signup ( ctx : Ctx ) -> None :
user_data = ctx . request . body
created_user = auth . sign_up ( user_data )
if created_user :
ctx . body = json . dumps ( created_user )
ctx . send ( 201 , content_type = 'application/json' )
else :
ctx . send ( 500 , content_type = 'application/json' )
def login ( ctx : Ctx ) -> None :
user_data = ctx . request . body
email = user_data [ 'email' ]
password = user_data [ 'password' ]
user_id , token = auth . login ( email , password )
print ( ctx . user , "HELLO FROM LOGIN" )
if token :
ctx . body = json . dumps ({ "message" : "Logged in successfully" , "token" : token })
ctx . set_res_header ( "Set-Cookie" , f"auth_token= { token } ; HttpOnly; Path=/" )
ctx . send ( 200 , content_type = 'application/json' )
# Set the token as a cookie or in the response headers
else :
ctx . body = json . dumps ({ "message" : "Invalid credentials" })
ctx . send ( 401 , content_type = 'application/json' )
def logout ( ctx : Ctx ) -> None :
auth . logout ( ctx )
ctx . body = json . dumps ({ "message" : "Logged out successfully" })
ctx . send ( 200 , content_type = 'application/json' )
@ Router . auth_required
def get_protected_content ( ctx : Ctx ) -> None :
ctx . body = json . dumps ({ "message" : "This is protected content. Only authenticated users can see this. I hope you feel special ???." })
ctx . send ( 200 , content_type = 'application/json' )
# ==================== API ROUTES ====================
# if you need to bind more variables to your handler, you can pass in a closure
api_router = Router ( prefix = '/api' )
api_router . post ( '/logout' , logout )
api_router . post ( '/login' , login )
api_router . post ( '/signup' , signup )
api_router . get ( '/hello' , api_hello_world )
# api_router.get('/users', get_and_delete_users)
api_router . get ( '/protected' , get_protected_content )
app . use ( hello_middle )
app . use ( auth . jwt_middleware )
app . use_router ( api_router )
app . start ()Yuzu ist so konzipiert, dass es flexibel ist und es Ihnen ermöglicht, es an die spezifischen Anforderungen Ihres Projekts anzupassen. Eine Möglichkeit, wie Sie sein Verhalten anpassen können, besteht darin, die Standardfunktionen des Standardkennworts und der Überprüfung zu ändern.
Standardmäßig verwendet Yuzu die bcrypt -Bibliothek für das Passworthashing und die Überprüfung. Wenn Sie einen anderen Ansatz verwenden möchten, können Sie Ihre eigenen Hashing- und Überprüfungsfunktionen an den Konstruktor der Yuzu -Klasse übergeben. Hier ist ein Beispiel dafür, wie es geht:
import hashlib
def my_hash_func ( password : str , salt : str = None ) -> str :
return hashlib . sha256 ( password . encode ()). hexdigest ()
def my_check_password_func ( password : str , hashed_password : str , salt : str = None ) -> bool :
return hashlib . sha256 ( password . encode ()). hexdigest () == hashed_password
auth = Yuzu ( keychain , get_user_by_email , create_user , hash_func = my_hash_func , checkpw_func = my_check_password_func )Die Verwendung von Argon2 für Hashing Argon2 ist ein moderner, sicheres Passwort -Hashing -Algorithmus, der vom Passwort -Hashing -Wettbewerb empfohlen wird. Hier ist ein Beispiel dafür, wie man es mit Yuzu verwendet:
from argon2 import PasswordHasher , exceptions
ph = PasswordHasher ( time_cost = 16 , memory_cost = 65536 )
def my_hash_func ( password : str , salt : str = None ) -> str :
return ph . hash ( password )
def my_check_password_func ( password : str , hashed_password : str , salt : str = None ) -> bool :
try :
return ph . verify ( hashed_password , password )
except exceptions . VerifyMismatchError :
return False
auth = Yuzu ( keychain , get_user_by_email , create_user , hash_func = my_hash_func , checkpw_func = my_check_password_func )Mit diesen Beispielen können Sie vom Standard -Bcrypt -Algorithmus auf SHA256 oder Argon2 wechseln. Sie können diese Funktionen auch ändern, um die Schwierigkeit der Hash -Funktion (z. B. die Anzahl der Iterationen oder die Speicherverwendung) gemäß Ihren spezifischen Anforderungen zu ändern.
Denken Sie daran, dass das Ändern dieser Funktionen Auswirkungen auf die Sicherheit Ihrer Anwendung haben kann. Sie sollten die Funktionsweise der gewählten Hash -Funktion und ihre Stärken und Schwächen verstehen, bevor Sie eine Entscheidung treffen.