اذهب إلى المحتوى

السؤال

نشر

أريد أن أقوم بإضافة ميزة تسجيل الدخول عبر رموز JWT في مشروع API مبني بإستخدام فلاسك Flask

هل توجد مكتبة أو حزمة تقوم بهذا الأمر؟ أم يجب أن أقوم به من الصفر بنفسي؟ وما هي خطوات بناء نظام إستيثاق Authentication في فلاسك Flask؟

Recommended Posts

  • 1
نشر

توجد مكتبة تساعد على القيام بذلك و هي مكتبة pyjwt، و هي مكتبة عامة للبايثون و ليس فقط لل Flask و بالطبع يمكنك استعمالها، و هي تقوم بترميز و فك ترميز الطلبات التي تحتوي على المعلومات المطلوبة لتسجيل الدخول.

و بالتالي يمكنك بناء ال request بشكل عادي و استعمال توابع هذه المكتبة للترميز بالشكل المطلوب.

كمثال على ذلك:

>>> import jwt
>>> encoded_jwt = jwt.encode({"some": "payload"}, "secret", algorithm="HS256")
>>> print(encoded_jwt)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCJ9.Joh1R2dYzkRvDkqv3sygm5YyK8Gi4ShZqbhK2gxcs2U
>>> jwt.decode(encoded_jwt, "secret", algorithms=["HS256"])
{'some': 'payload'}

 

  • 1
نشر

نعم بإستعمال مكتبة PyJWT تستطيع عمل مصادقة او authentication مع إطار العمل flask 

الخطوات :

  1. نقوم بإنشاء ملف requirements.txt ونضع فيه الأتي :
  2. Flask-RESTful==0.3.8
    PyJWT==1.7.1
    Flask-SQLAlchemy==2.4.1

     

  3. نفعل البيئة الإفتراضية source env/bin/activate  

  4. ثم نحمل المكتبات بهذا الأمر    pip install -r requirements.txt

الآن ، انتهينا من جزء الإعداد. لنبدأ الآن في كتابة الكود الفعلي. قبل البدء بالكود ، أود أن أوضح شيئًا. سأكتب الكود بأكمله في ملف واحد ، أي نماذج قاعدة البيانات والمسارات معًا ، وهي ليست ممارسة جيدة وبالتأكيد لا يمكن إدارتها للمشاريع الأكبر. حاول الاحتفاظ بإنشاء ملفات أو وحدات بيثون منفصلة للطرق ونماذج قواعد البيانات.

# جزء استيراد المكتبات
from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
import uuid # لإنشاء معرفات يصعب التعرف عليها
from werkzeug.security import generate_password_hash, check_password_hash
# استيراد jwt 
import jwt
from datetime import datetime, timedelta
from functools import wraps

# انشاء flask objects 
app = Flask(__name__)
# الإعدادات
#نصيحة : لا تقم بوضع الرموز الحساسة في ملفات الكود
# قم بالعمل مع مكتبة decouple 
app.config['SECRET_KEY'] = 'رمزك السري'
# اسم قاعدة البيانات
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///Database.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# إنشاء SQLALCHEMY object
db = SQLAlchemy(app)

# جدول المستخدم 
class User(db.Model):
	id = db.Column(db.Integer, primary_key = True)
	public_id = db.Column(db.String(50), unique = True)
	name = db.Column(db.String(100))
	email = db.Column(db.String(70), unique = True)
	password = db.Column(db.String(80))

# نقوم بعمل ديكورايتور لتحقق من مصادقة jwt
def token_required(f):
	@wraps(f)
	def decorated(*args, **kwargs):
		token = None
		# jwt يمرر في رأسية الإستعلام او headers 
		if 'x-access-token' in request.headers:
			token = request.headers['x-access-token']
		# نقوم بإرجاع رمز 401 اذا كان الرمز غير صالح
		if not token:
			return jsonify({'message ':'لا يوجد الرمز'}), 401

		try:
			# فك تشفير التوكن
			data = jwt.decode(token, app.config['SECRET_KEY'])
			current_user = User.query\
				.filter_by(public_id = data['public_id'])\
				.first()
		except:
			return jsonify({
				'message' : ' خطأ في الرمز  !!'
			}), 401
		# نقوم بإرجاع المسخدمين النشطين او يمكنك ارجاع ما شأت
		return f(current_user, *args, **kwargs)

	return decorated


# مسار المصادقة على المستخدم
@app.route('/login', methods =['POST'])
def login():
	# ننشأ قاموس او dictionary 
    # من أجل استعلام الفورم
	auth = request.form

	if not auth or not auth.get('email') or not auth.get('password'):
		# نرجع الرمز 401 اذا لم بقم بملأ البيانات كاملة
		return make_response(
			'الرجاء ملأ البيانات',
			401,
			{'WWW-Authenticate' : 'Basic realm ="يرجى تسجيل الدخول !!"'}
		)

	user = User.query\
		.filter_by(email = auth.get('email'))\
		.first()

	if not user:
		# ارجاع 401 اذا كان المستخدم غير موجود
		return make_response(
			'غير موجود',
			401,
			{'WWW-Authenticate' : 'Basic realm ="المستخدم غير موجود !!"'}
		)

	if check_password_hash(user.password, auth.get('password')):
		# إنشاء الرمز للتحقق
		token = jwt.encode({
			'public_id': user.public_id,
			'exp' : datetime.utcnow() + timedelta(minutes = 30)
		}, app.config['SECRET_KEY'])

		return make_response(jsonify({'token' : token.decode('UTF-8')}), 201)
	# نرجع 403 اذا أخطأ في كلمة السر
	return make_response(
		'خطأ',
		403,
		{'WWW-Authenticate' : 'Basic realm ="كلمة المرور خاطئة !!"'}
	)


if __name__ == "__main__":

	app.run(debug = True)

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...