Tangerine-Auth هي مكتبة Python توفر الأدوات المساعدة لمصادقة المستخدم والتعامل الآمن للمفاتيح والبيانات المشفرة. يستخدم BCrypt لجامس كلمة المرور و JWT للمصادقة المستندة إلى الرمز المميز.
ملاحظة: Tangerine-Auth موجود حاليًا في الإصدار التجريبي. لا ينصح باستخدام الإنتاج حتى الآن. لا تتردد في التنزيل واللعب معها في هذه الأثناء! نحن نعمل على إضافة المزيد من الاختبارات والوثائق. إذا وجدت أي أخطاء أو لديك أي اقتراحات ، فيرجى فتح مشكلة على Github.
استخدم PIP لتثبيت الحزمة:
pip install tangerine-authالخطوات العامة لدمج Yuzu في طلبك هي كما يلي:
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' ]}قم بإنشاء كائن Keylime ونقله إلى مُنشئ Yuzu. يتم استخدام كائن Keylime للتعامل بشكل آمن والبيانات المشفرة. يمكنك استخدام كائن Keylime لتشفير البيانات وفك تشفيرها ، وتخزين واسترداد المفاتيح.
قم بإنشاء كائن yuzu وقم بتمرير كائن Keylime ، والوظيفة لإيجاد مستخدم في قاعدة البيانات الخاصة بك ، ووظيفة إنشاء مستخدم في قاعدة البيانات الخاصة بك.
(اختياري) يستخدم Yuzu Bcrypt إلى كلمات مرور التجزئة. يمكنك اختياريًا تمرير وظيفة التجزئة المخصصة إلى مُنشئ Yuzu. يجب أن تأخذ وظيفة التجزئة المخصصة سلسلة كلمة مرور كوسيطة وإرجاع سلسلة كلمة مرور التجزئة.
بعد اكتمال الخطوة 3 ، يمكنك الآن استخدام كائن Yuzu للتسجيل مستخدمًا جديدًا ، وتسجيل الدخول إلى مستخدم ، وتسجيل الخروج من مستخدم ، والتحقق من رموز المصادقة.
تم بناء Yuzu للعمل مع Flask وكذلك Tangerine ، يوجد حاليًا اثنين من الأدوات المتوسطة JWT مع Yuzu ، واحدة للقرار وواحدة من أجل Tangerine. بمجرد تهيئة فئة Yuzu بشكل صحيح ، يمكنك استخدام البرامج الوسيطة اليوسفي عن طريق الاتصال:
app . use ( auth . jwt_middleware ).لا يزال إصدار Flask JWT Middleware تجريبيًا ، ويمكن أن يكون عرضًا. لن يتم التوصية به لاستخدام الإنتاج حتى يتم اختباره بشكل أكثر شمولية. يعمل JWT Middleware بشكل مختلف قليلاً في Flask ، لاستخدامه مع Flask ، يمكنك استخدامه كديكور:
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 )ملاحظة: يقوم المصادف الوسيطة بإلحاق بيانات المستخدم إلى كائن CTX. يمكنك الوصول إلى بيانات المستخدم في معالج المسار الخاص بك عن طريق الاتصال
ctx . auth . user or ctx . get ( "user" )Yuzu هو فئة توفر وظائف مصادقة المستخدم. يستخدم BCrypt لجلب كلمة المرور و JWT لإنشاء رموز المصادقة والتحقق منها.
فيما يلي الطرق الرئيسية لفئة Yuzu:
- `__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 هو فئة توفر وظائف للتعامل مع مفاتيح التعامل بشكل آمن والبيانات المشفرة.
فيما يلي الطرق الرئيسية لفئة Keylime:
- `__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 .المخروط العام لهذا هو أنك تريد كتابة وظيفتين ، واحدة لإيجاد مستخدم في نظام قاعدة البيانات الذي اخترته ، وواحد لإنشاء مستخدم في نظام قاعدة البيانات المختار. يجب أن تأخذ هذه الوظائف قاموسًا لبيانات المستخدم كوسيطة وإرجاع قاموس بيانات المستخدم. يجب أن يحتوي قاموس بيانات المستخدم على حقل بريد إلكتروني وكلمة مرور على الأقل. يمكن أن يحتوي قاموس بيانات المستخدم على أي حقول أخرى تريد تخزينها في قاعدة البيانات الخاصة بك.
فيما يلي مثال على كيفية استخدام فئات Yuzu و Keylime:
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 لتكون مرنًا ، مما يتيح لك تكييفه مع الاحتياجات المحددة لمشروعك. إحدى الطرق التي يمكنك من خلالها تخصيص سلوكها هي تغيير وظائف التجزئة والتحقق من كلمة المرور الافتراضية.
افتراضيًا ، يستخدم Yuzu مكتبة bcrypt لجامس كلمة المرور والتحقق. إذا كنت ترغب في استخدام نهج مختلف ، فيمكنك تمرير وظائف التجزئة والتحقق إلى مُنشئ فئة Yuzu. إليك مثال على كيفية القيام بذلك:
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 )إن استخدام Argon2 لـ Hashing Argon2 هو خوارزمية تجزئة كلمة المرور الحديثة والآمنة التي تنصح بها مسابقة تجزئة كلمة المرور. إليك مثال على كيفية استخدامه مع Yuzu:
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 )تتيح لك هذه الأمثلة التبديل من خوارزمية BCrypt الافتراضية إلى SHA256 أو Argon2. يمكنك أيضًا تعديل هذه الوظائف لتغيير صعوبة وظيفة التجزئة (على سبيل المثال ، عن طريق زيادة عدد التكرارات أو استخدام الذاكرة) وفقًا لمتطلباتك المحددة.
تذكر أن تغيير هذه الوظائف يمكن أن يكون لها آثار على أمان التطبيق الخاص بك. يجب أن تفهم أعمال وظيفة التجزئة المختارة ونقاط القوة والضعف قبل اتخاذ قرار.