المصادقة باستخدام مفتاح ملفات تعريف الارتباط مع رد اتصال غير متزامن

StackOverflow https://stackoverflow.com/questions/2848907

سؤال

أحتاج إلى كتابة وظيفة المصادقة مع رد اتصال غير متزامن من API Auth Auth عن بُعد. المصادقة البسيطة مع تسجيل الدخول تعمل بشكل جيد ، ولكن التفويض باستخدام ملف تعريف الارتباط ، لا يعمل. يجب أن يتحقق ما إذا كان في ملفات تعريف الارتباط التي تقدم المفتاح "LP_LOGIN" ، جلب URL API مثل ASYNC وتنفيذ وظيفة ON_RESPONSE.

يعمل الرمز تقريبًا ، لكني أرى مشكلتين. أولاً ، في وظيفة ON_RESPONSE ، أحتاج إلى إعداد ملف تعريف ارتباط آمن للمستخدم المعتمد في كل صفحة. في الكود user_id يقوم بإرجاع المعرف الصحيح ، ولكن السطر: self.set_secure_cookie ("المستخدم" ، user_id) لا يعمل. لماذا يمكن أن يكون؟

والمشكلة الثانية. أثناء ASYNC FETCH API url ، تم تحميل صفحة المستخدم قبل ملف تعريف الارتباط ON_RESPONSE SETUP باستخدام مفتاح "المستخدم" وستكون الصفحة قسم غير مصرح بها مع رابط لتسجيل الدخول أو تسجيل الدخول. سيكون مربكا للمستخدمين. لحلها ، يمكنني إيقاف صفحة التحميل للمستخدم الذي يحاول تحميل الصفحة الأولى من الموقع. هل من الممكن أن تفعل وكيف؟ ربما يكون للمشكلة طريقة أكثر صحيحة لحلها؟

class BaseHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get_current_user(self):
        user_id = self.get_secure_cookie("user")
        user_cookie = self.get_cookie("lp_login")
        if user_id:
            self.set_secure_cookie("user", user_id)
            return Author.objects.get(id=int(user_id))
        elif user_cookie:
            url = urlparse("http://%s" % self.request.host)
            domain = url.netloc.split(":")[0]
            try:
                username, hashed_password = urllib.unquote(user_cookie).rsplit(',',1)
            except ValueError:
                # check against malicious clients
                return None
            else:
                url = "http://%s%s%s/%s/" % (domain, "/api/user/username/", username, hashed_password)
                http = tornado.httpclient.AsyncHTTPClient()
                http.fetch(url, callback=self.async_callback(self.on_response))
        else:
            return None

    def on_response(self, response):
        answer = tornado.escape.json_decode(response.body)
        username = answer['username']
        if answer["has_valid_credentials"]:
            author = Author.objects.get(email=answer["email"])
            user_id = str(author.id)
            print user_id # It returns needed id
            self.set_secure_cookie("user", user_id) # but session can's setup
هل كانت مفيدة؟

المحلول

يبدو أنك تتقاطع مع هذا في قائمة المراسلة Tornado هنا

واحدة من المشكلات التي تواجهها هي أنه لا يمكنك بدء مكالمة Async بداخلها get_current_user, ، يمكنك فقط بدء مكالمة غير متزامنة من شيء يحدث داخل get أو post.

لم أختبرها ، لكنني أعتقد أن هذا يجب أن يجعلك على مقربة مما تبحث عنه.

#!/bin/python
import tornado.web
import tornado.http
import tornado.escape
import functools
import logging
import urllib

import Author

def upgrade_lp_login_cookie(method):
    @functools.wraps(method)
    def wrapper(self, *args, **kwargs):
        if not self.current_user and self.get_cookie('lp_login'):
            self.upgrade_lp_login(self.async_callback(method, self, *args, **kwargs))
        else:
            return method(self, *args, **kwargs)
    return wrapper


class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        user_id = self.get_secure_cookie("user")
        if user_id:
            return Author.objects.get(id=int(user_id))

    def upgrade_lp_login(self, callback):
        lp_login = self.get_cookie("lp_login")
        try:
            username, hashed_password = urllib.unquote(lp_login).rsplit(',',1)
        except ValueError:
            # check against malicious clients
            logging.info('invalid lp_login cookie %s' % lp_login)
            return callback()

        url = "http://%(host)s/api/user/username/%s/%s" % (self.request.host, 
                                                        urllib.quote(username), 
                                                        urllib.quote(hashed_password))
        http = tornado.httpclient.AsyncHTTPClient()
        http.fetch(url, self.async_callback(self.finish_upgrade_lp_login, callback))

    def finish_upgrade_lp_login(self, callback, response):
        answer = tornado.escape.json_decode(response.body)
        # username = answer['username']
        if answer['has_valid_credentials']:
            # set for self.current_user, overriding previous output of self.get_current_user()
            self._current_user = Author.objects.get(email=answer["email"])
            # set the cookie for next request
            self.set_secure_cookie("user", str(self.current_user.id))

        # now chain to the real get/post method
        callback()

    @upgrade_lp_login_cookie
    def get(self):
        self.render('template.tmpl')
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top