دمج تسجيل الدخول إلى Facebook في تطبيق AngularJS مع Satellizer

نشرت: 2022-03-11

مع وصول أطر أمامية غنية بالميزات مثل AngularJS ، يتم تنفيذ المزيد والمزيد من المنطق على الواجهة الأمامية ، مثل معالجة البيانات / التحقق من الصحة والمصادقة والمزيد. Satellizer ، وحدة المصادقة القائمة على الرموز سهلة الاستخدام لـ AngularJS ، تبسط عملية تنفيذ آلية المصادقة في AngularJS ، تأتي المكتبة مع دعم مدمج لـ Google و Facebook و LinkedIn و Twitter و Instagram و GitHub و Bitbucket و Yahoo و Twitch و Microsoft (Windows Live).

في هذه المقالة ، سننشئ تطبيق ويب بسيطًا جدًا مشابهًا لذلك الموجود هنا والذي يسمح لك بتسجيل الدخول والاطلاع على معلومات المستخدم الحالية.

المصادقة مقابل التفويض

هاتان كلمتان مخيفتان غالبًا ما تصادفهما بمجرد أن يبدأ تطبيقك في دمج نظام مستخدم. بحسب ويكيبيديا:

المصادقة هي عملية تأكيد حقيقة سمة لقطعة واحدة من البيانات (مسند) يدعي الكيان أنها صحيحة.

التخويل هو وظيفة تحديد حقوق الوصول إلى الموارد المتعلقة بأمن المعلومات وأمن الكمبيوتر بشكل عام والتحكم في الوصول بشكل خاص.

بعبارات عامة ، لنأخذ مثالاً على موقع ويب للمدونة يعمل عليه بعض الأشخاص. يكتب المدونون مقالات ويقوم المدير بالتحقق من صحة المحتوى. يمكن لكل شخص المصادقة (تسجيل الدخول) في النظام ولكن حقوقهم (التفويض) مختلفة ، لذلك لا يمكن للمدون التحقق من صحة المحتوى بينما يستطيع المدير ذلك.

لماذا ستيلزر

يمكنك إنشاء نظام المصادقة الخاص بك في AngularJS باتباع بعض البرامج التعليمية مثل هذا البرنامج المفصل للغاية: JSON Web Token Tutorial: مثال في Laravel و AngularJS. أقترح قراءة هذه المقالة لأنها تشرح JWT (JSON Web Token) جيدًا ، وتوضح طريقة بسيطة لتنفيذ المصادقة في AngularJS باستخدام التخزين المحلي واعتراضات HTTP مباشرة.

فلماذا ستيلزر؟ السبب الرئيسي هو أنه يدعم عددًا قليلاً من عمليات تسجيل الدخول إلى الشبكات الاجتماعية مثل Facebook و Twitter وما إلى ذلك. في الوقت الحاضر ، خاصة بالنسبة لمواقع الويب المستخدمة على الهاتف المحمول ، تعد كتابة اسم المستخدم وكلمة المرور مرهقة للغاية ويتوقع المستخدمون أن يكونوا قادرين على استخدام موقع الويب الخاص بك مع القليل من العوائق باستخدام عمليات تسجيل الدخول الاجتماعية. نظرًا لأن دمج SDK لكل شبكة اجتماعية واتباع وثائقهم أمر متكرر تمامًا ، سيكون من الجيد دعم عمليات تسجيل الدخول الاجتماعية هذه بأقل جهد ممكن.

علاوة على ذلك ، فإن Satellizer هو مشروع نشط على Github. النشط هو المفتاح هنا حيث تتغير مجموعات SDK هذه بشكل متكرر ولا تريد قراءة وثائقها بين الحين والآخر (يعرف أي شخص يعمل مع Facebook SDK كم هو مزعج)

تطبيق AngularJS مع تسجيل الدخول إلى Facebook

هذا هو المكان الذي تبدأ فيه الأشياء تصبح مثيرة للاهتمام.

سنقوم ببناء تطبيق ويب يحتوي على آلية تسجيل دخول / تسجيل منتظمة (أي باستخدام اسم المستخدم وكلمة المرور) ويدعم عمليات تسجيل الدخول الاجتماعية أيضًا. تطبيق الويب هذا بسيط للغاية لأنه يحتوي على 3 صفحات فقط:

  • الصفحة الرئيسية: يمكن لأي شخص أن يرى
  • صفحة تسجيل الدخول: لإدخال اسم المستخدم / كلمة المرور
  • الصفحة السرية: يمكن فقط للمستخدمين الذين قاموا بتسجيل الدخول رؤيتها

بالنسبة للخلفية ، سوف نستخدم Python و Flask. Python و framework Flask معبرتان تمامًا لذا آمل ألا يكون نقل الكود إلى لغات / أطر عمل أخرى صعبًا للغاية. سنستخدم بالطبع AngularJS للواجهة الأمامية. وبالنسبة لعمليات تسجيل الدخول الاجتماعية ، سنقوم بالتكامل مع Facebook فقط لأنه أكثر الشبكات الاجتماعية شيوعًا في هذا الوقت.

لنبدأ!

الخطوة رقم 1: مشروع Bootstrap

إليك كيفية هيكلة الكود الخاص بنا:

 - app.py - static/ - index.html - app.js - bower.json - partials/ - login.tpl.html - home.tpl.html - secret.tpl.html

كل كود النهاية موجود في app.py. يتم وضع كود الواجهة الأمامية في مجلد ثابت / ثابت. بشكل افتراضي ، سيقوم Flask تلقائيًا بخدمة محتويات ثابت / مجلد. جميع العروض الجزئية ثابتة / جزئية / ويتم التعامل معها بواسطة وحدة ui.router.

لبدء تشفير النهاية الخلفية ، سنحتاج إلى Python 2.7. * وتثبيت المكتبات المطلوبة باستخدام النقطة. يمكنك بالطبع استخدام virtualenv لعزل بيئة Python. فيما يلي قائمة بوحدات Python النمطية المطلوبة لوضع المتطلبات. txt:

 Flask==0.10.1 PyJWT==1.4.0 Flask-SQLAlchemy==1.0 requests==2.7.0

لتثبيت كل هذه التبعيات:

 pip install -r requirements.txt

في app.py ، لدينا بعض التعليمات البرمجية الأولية لـ bootstrap Flask (تم حذف عبارات الاستيراد للإيجاز):

 app = Flask(__name__) @app.route('/') def index(): return flask.redirect('/static/index.html') if __name__ == '__main__': app.run(debug=True)

بعد ذلك ، بدأنا التعريشة وقمنا بتثبيت AngularJS و ui.router:

 bower init # here you will need to answer some question. when in doubt, just hit enter :) bower install angular angular-ui-router --save # install and save these dependencies into bower.json

بمجرد تثبيت هذه المكتبات ، نحتاج إلى تضمين AngularJS و ui-router في index.html وإنشاء مسارات لثلاث صفحات: الصفحة الرئيسية وتسجيل الدخول والسرية.

 <body ng-app="DemoApp"> <a ui-sref="home">Home</a> <a ui-sref="login">Login</a> <a ui-sref="secret">Secret</a> <div ui-view></div> <script src="bower_components/angular/angular.min.js"></script> <script src="bower_components/angular-ui-router/release/angular-ui-router.min.js"></script> <script src="main.js"></script> </body>

يوجد أدناه الكود الذي نحتاجه في main.js لتهيئة التوجيه:

 var app = angular.module('DemoApp', ['ui.router']); app.config(function ($stateProvider, $urlRouterProvider) { $stateProvider .state('home', { url: '/home', templateUrl: 'partials/home.tpl.html' }) .state('secret', { url: '/secret', templateUrl: 'partials/secret.tpl.html', }) .state('login', { url: '/login', templateUrl: 'partials/login.tpl.html' }); $urlRouterProvider.otherwise('/home'); });

في هذه المرحلة ، إذا قمت بتشغيل خادم python app.py ، فيجب أن يكون لديك هذه الواجهة الأساسية على http: // localhost: 5000

واجهة تسجيل الدخول الأساسية

يجب أن تعمل الروابط الرئيسية وتسجيل الدخول والسرية في هذه المرحلة وأن تعرض محتوى القوالب المقابلة.

تهانينا ، لقد انتهيت للتو من إنشاء الهيكل العظمي! إذا واجهت أي خطأ ، فالرجاء التحقق من الكود على GitHub

الخطوة رقم 2: تسجيل الدخول والتسجيل

في نهاية هذه الخطوة ، سيكون لديك تطبيق ويب يمكنك التسجيل / تسجيل الدخول باستخدام البريد الإلكتروني وكلمة المرور.

الخطوة الأولى هي تكوين الواجهة الخلفية. نحتاج إلى نموذج مستخدم وطريقة لإنشاء رمز JWT لمستخدم معين. نموذج المستخدم الموضح أدناه مبسط حقًا ولا يقوم بأي عمليات فحص أساسية ، مثل ما إذا كان حقل البريد الإلكتروني يحتوي على "@" ، أو إذا كانت كلمة مرور الحقل تحتوي على 6 أحرف على الأقل ، وما إلى ذلك.

 class User(db.Model): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(100), nullable=False) password = db.Column(db.String(100)) def token(self): payload = { 'sub': self.id, 'iat': datetime.utcnow(), 'exp': datetime.utcnow() + timedelta(days=14) } token = jwt.encode(payload, app.config['TOKEN_SECRET']) return token.decode('unicode_escape')

نستخدم الوحدة النمطية jwt في لغة python لتوليد جزء الحمولة في JWT. يتوافق الجزء iat و exp مع الطابع الزمني الذي تم إنشاؤه وانتهاء صلاحيته. في هذا الرمز ، ستنتهي صلاحية الرمز المميز في غضون أسبوعين.

بعد إنشاء المستخدم النموذجي ، يمكننا إضافة نقطتي النهاية "تسجيل الدخول" و "التسجيل". رمز كلاهما متشابه تمامًا ، لذا سأعرض هنا جزء "التسجيل" فقط. يرجى ملاحظة أنه بشكل افتراضي ، سوف يستدعي Satellizer نقاط النهاية / auth / login و / auth / signup من أجل "تسجيل الدخول" و "التسجيل" على التوالي.

 @app.route('/auth/signup', methods=['POST']) def signup(): data = request.json email = data["email"] password = data["password"] user = User(email=email, password=password) db.session.add(user) db.session.commit() return jsonify(token=user.token())

دعنا نتحقق من نقطة النهاية باستخدام curl أولاً:

 curl localhost:5000/auth/signup -H "Content-Type: application/json" -X POST -d '{"email":"[email protected]","password":"xyz"}'

يجب أن تبدو النتيجة كما يلي:

 { "token": "very long string…." }

الآن بعد أن أصبح الجزء الخلفي جاهزًا ، فلنهاجم الواجهة الأمامية! أولاً ، نحتاج إلى تثبيت satellizer وإضافته كاعتماد في main.js:

 bower install satellizer --save

إضافة القمر الصناعي كتبعية:

 var app = angular.module('DemoApp', ['ui.router', 'satellizer']);

تسجيل الدخول والاشتراك في satellizer هو في الواقع بسيط للغاية مقارنة بجميع الإعدادات حتى الآن:

 $scope.signUp = function () { $auth .signup({email: $scope.email, password: $scope.password}) .then(function (response) { // set the token received from server $auth.setToken(response); // go to secret page $state.go('secret'); }) .catch(function (response) { console.log("error response", response); }) };

إذا واجهت أي صعوبة في إعداد الكود ، يمكنك إلقاء نظرة على الكود على GitHub.

الخطوة # 3: لكن العرض السري ليس سرًا حقًا ، لأن أي شخص يمكنه رؤيته!

نعم هذا صحيح! حتى الآن ، يمكن لأي شخص الانتقال إلى صفحة سرية دون تسجيل الدخول.

حان الوقت لإضافة بعض المعترض في AngularJS للتأكد من أنه إذا انتقل شخص ما إلى صفحة سرية وإذا لم يقم هذا المستخدم بتسجيل الدخول ، فسيتم إعادة توجيهه إلى صفحة تسجيل الدخول.

أولاً ، يجب إضافة علامة requiredLogin لتمييز الصفحة السرية عن الصفحات الأخرى.

 .state('secret', { url: '/secret', templateUrl: 'partials/secret.tpl.html', controller: 'SecretCtrl', data: {requiredLogin: true} })

سيتم استخدام جزء "البيانات" في حدث $ stateChangeStart الذي يتم تشغيله في كل مرة يتغير فيها التوجيه:

 app.run(function ($rootScope, $state, $auth) { $rootScope.$on('$stateChangeStart', function (event, toState) { var requiredLogin = false; // check if this state need login if (toState.data && toState.data.requiredLogin) requiredLogin = true; // if yes and if this user is not logged in, redirect him to login page if (requiredLogin && !$auth.isAuthenticated()) { event.preventDefault(); $state.go('login'); } }); });

الآن ، لا يمكن للمستخدم الانتقال مباشرة إلى الصفحة السرية دون تسجيل الدخول. مرحى!

كالعادة ، يمكن العثور على رمز هذه الخطوة هنا.

الخطوة رقم 4: حان الوقت للحصول على شيء سرّي حقًا!

في هذه اللحظة ، لا يوجد شيء سري حقًا في الصفحة السرية. دعونا نضع شيئًا شخصيًا هناك.

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

 @app.route('/user') def user_info(): # the token is put in the Authorization header if not request.headers.get('Authorization'): return jsonify(error='Authorization header missing'), 401 # this header looks like this: “Authorization: Bearer {token}” token = request.headers.get('Authorization').split()[1] try: payload = jwt.decode(token, app.config['TOKEN_SECRET']) except DecodeError: return jsonify(error='Invalid token'), 401 except ExpiredSignature: return jsonify(error='Expired token'), 401 else: user_id = payload['sub'] user = User.query.filter_by(id=user_id).first() if user is None: return jsonify(error='Should not happen ...'), 500 return jsonify(id=user.id, email=user.email), 200 return jsonify(error="never reach here..."), 500

مرة أخرى ، نستخدم الوحدة النمطية jwt لفك تشفير رمز JWT المتضمن في رأس "التفويض" وللتعامل مع الحالة عند انتهاء صلاحية الرمز المميز أو عدم صلاحيته.

دعنا نختبر نقطة النهاية هذه باستخدام curl. أولاً ، نحتاج إلى الحصول على رمز مميز صالح:

 curl localhost:5000/auth/signup -H "Content-Type: application/json" -X POST -d '{"email":"[email protected]","password":"xyz"}'

ثم مع هذا الرمز المميز:

 curl localhost:5000/user -H "Authorization: Bearer {put the token here}"

والذي يعطي هذه النتيجة:

 { "email": "[email protected]", "id": 1 }

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

 getUserInfo(); function getUserInfo() { $http.get('/user') .then(function (response) { $scope.user = response.data; }) .catch(function (response) { console.log("getUserInfo error", response); }) }

أخيرًا ، لدينا شيء شخصي حقًا في الصفحة السرية!

الصفحة السرية ، والتي تظهر البريد الإلكتروني للمستخدم والمعرف.

رمز هذه الخطوة موجود على جيثب.

الخطوة # 5: تسجيل الدخول إلى Facebook باستخدام Satellizer

الشيء الجميل في برنامج Satellizer ، كما ذكرنا في البداية ، هو أنه يجعل دمج تسجيل الدخول الاجتماعي أسهل كثيرًا. في نهاية هذه الخطوة ، يمكن للمستخدمين تسجيل الدخول باستخدام حساب Facebook الخاص بهم!

مصادقة Facebook OAuth.

أول شيء يجب القيام به هو إنشاء تطبيق على صفحة مطوري Facebook من أجل الحصول على معرف التطبيق ورمز سري. يرجى اتباع developer.facebook.com/docs/apps/register لإنشاء حساب مطور Facebook إذا لم يكن لديك حساب بالفعل وإنشاء تطبيق موقع ويب. بعد ذلك ، سيكون لديك معرف التطبيق وسر التطبيق كما في لقطة الشاشة أدناه.

الحصول على سر التطبيق.

بمجرد أن يختار المستخدم الاتصال بـ Facebook ، سيرسل Satellizer رمز ترخيص إلى نقطة النهاية / المصادقة / facebook . باستخدام رمز التفويض هذا ، يمكن للواجهة الخلفية استرداد رمز وصول من نقطة نهاية Facebook / oauth التي تتيح الاتصال بواجهة برمجة تطبيقات Facebook Graph للحصول على معلومات المستخدم مثل الموقع وأصدقاء المستخدم والبريد الإلكتروني للمستخدم وما إلى ذلك.

نحتاج أيضًا إلى تتبع ما إذا كان قد تم إنشاء حساب مستخدم باستخدام Facebook أو من خلال الاشتراك المنتظم. للقيام بذلك ، أضفنا facebook_id إلى نموذج المستخدم الخاص بنا.

 facebook_id = db.Column(db.String(100))

يتم تكوين سر facebook عبر متغيرات env FACEBOOK_SECRET التي نضيفها إلى app.config .

 app.config['FACEBOOK_SECRET'] = os.environ.get('FACEBOOK_SECRET')

لذلك لتشغيل app.py ، يجب عليك تعيين متغير env:

 FACEBOOK_SECRET={your secret} python app.py

هذه هي الطريقة التي تتعامل مع عمليات تسجيل الدخول إلى Facebook. بشكل افتراضي ، سوف يستدعي Satellizer نقطة النهاية / auth / facebook .

 @app.route('/auth/facebook', methods=['POST']) def auth_facebook(): access_token_url = 'https://graph.facebook.com/v2.3/oauth/access_token' graph_api_url = 'https://graph.facebook.com/v2.5/me?fields=id,email' params = { 'client_id': request.json['clientId'], 'redirect_uri': request.json['redirectUri'], 'client_secret': app.config['FACEBOOK_SECRET'], 'code': request.json['code'] } # Exchange authorization code for access token. r = requests.get(access_token_url, params=params) # use json.loads instead of urlparse.parse_qsl access_token = json.loads(r.text) # Step 2. Retrieve information about the current user. r = requests.get(graph_api_url, params=access_token) profile = json.loads(r.text) # Step 3. Create a new account or return an existing one. user = User.query.filter_by(facebook_id=profile['id']).first() if user: return jsonify(token=user.token()) u = User(facebook_id=profile['id'], email=profile['email']) db.session.add(u) db.session.commit() return jsonify(token=u.token())

لإرسال طلب إلى خادم Facebook ، نستخدم طلبات الوحدة سهلة الاستخدام. الآن تم الانتهاء من الجزء الصعب في النهاية الخلفية. في الواجهة الأمامية ، تعد إضافة تسجيل الدخول إلى Facebook أمرًا بسيطًا للغاية. أولاً ، نحتاج إلى إخبار Satellizer لدينا facebook_id عن طريق إضافة هذا الرمز إلى وظيفة app.config :

 $authProvider.facebook({ clientId: {your facebook app id}, // by default, the redirect URI is http://localhost:5000 redirectUri: 'http://localhost:5000/static/index.html' });

لتسجيل الدخول باستخدام Facebook ، يمكننا فقط الاتصال بـ:

 $auth.authenticate(“facebook”)

كالعادة ، يمكنك التحقق من الكود على GitHub

في هذا الوقت ، يكتمل تطبيق الويب من حيث الوظائف. يمكن للمستخدم تسجيل الدخول / التسجيل باستخدام البريد الإلكتروني العادي وكلمة المرور أو باستخدام Facebook. بمجرد تسجيل الدخول ، يمكن للمستخدم رؤية صفحته السرية.

إنشاء واجهة جميلة

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

يمكن العثور على رمز هذا الجزء التجميلي هنا.

خاتمة

تعرض هذه المقالة تكاملًا خطوة بخطوة لبرنامج Satellizer في تطبيق ويب AngularJS (بسيط). باستخدام Satellizer ، يمكننا بسهولة إضافة معلومات تسجيل دخول اجتماعية أخرى مثل Twitter و Linkedin والمزيد. الكود الموجود في الواجهة الأمامية هو نفسه تمامًا كما في المقالة. ومع ذلك ، تختلف النهاية الخلفية نظرًا لأن حزم SDK للشبكات الاجتماعية لها نقاط نهاية مختلفة ببروتوكولات مختلفة. يمكنك إلقاء نظرة على https://github.com/sahat/satellizer/blob/master/examples/server/python/app.py الذي يحتوي على أمثلة لـ Facebook و Github و Google و Linkedin و Twiter و Bitbucket. في حالة الشك ، يجب عليك إلقاء نظرة على الوثائق الموجودة على https://github.com/sahat/satellizer.

ذات صلة: تسجيل الدخول بنقرة واحدة باستخدام Blockchain: برنامج تعليمي MetaMask