Frage

Ich brauche Authentifizierungsfunktion mit asynchronem Rückruf von Remote-Auth-API zu schreiben. Einfache Authentifizierung mit Login funktioniert gut, aber Genehmigung mit Cookie-Taste funktioniert nicht. Es sollte überprüft, ob in Cookies vorhanden Schlüssel "lp_login", API URL wie async holen und ausführen on_response Funktion.

Der Code fast funktioniert, aber ich sehe zwei Probleme. Zuerst in on_response Funktion muss ich Setup sicheres Cookie für autorisierte Benutzer auf jeder Seite. In Code user_id gibt korrekte ID, aber Zeile: self.set_secure_cookie ( "user", user_id) does't Arbeit. Warum kann es sein?

Und zweites Problem. Während Asynchron-API-URL holen, Seite des Benutzers vor on_response Setup-Cookie geladen mit der Taste „Benutzer“ und die Seite hat einen nicht autorisierten Abschnitt mit Link zur Anmeldung oder anmelden. Es wird verwirrend für die Nutzer sein. Um es zu lösen, kann ich Laden Seite für den Benutzer stoppen, die erste Seite der Website zu laden versuchen. Ist es möglich, zu tun und wie? Vielleicht ist das Problem hat richtigere Weg, es zu lösen?

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
War es hilfreich?

Lösung

Es scheint, dass Sie dies auf der Tornado-Mailingliste Cross-Gepostet hier

Eines der Probleme, die Sie in laufen ist, dass Sie nicht von dem Asynchron-Anruf innerhalb von get_current_user starten können, können Sie nur einen Asynchron-Anruf von etwas beginnen, das innerhalb von get oder post passiert.

Ich habe es nicht getestet, aber ich denke, das sollte Sie in der Nähe bekommen, was Sie suchen.

#!/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')
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top