Domanda

I bisogno di scrivere funzione di autenticazione con callback asincrono da API autenticazione remota. autenticazione semplice con login sta lavorando bene, ma l'autorizzazione con chiave biscotto, non funziona. Dovrebbe controlla se nei cookie chiave presente "lp_login", prendere API URL tipo asincrono ed eseguire on_response funzione.

Il codice funziona quasi, ma vedo due problemi. In primo luogo, in funzione on_response Devo installare cookie sicuro per l'utente autorizzato in ogni pagina. Nel codice user_id torna ID corretto, ma la linea: self.set_secure_cookie ( "utente", user_id) lavoro does't. Perché può essere?

E secondo problema. Durante asincrona prendere API URL, pagina utente ha caricato prima biscotto configurazione on_response con il tasto "utente" e la pagina volontà ha una sezione non autorizzata con il link per accedere o imbarcarsi. Sarà confusione per gli utenti. Per risolverlo, posso smettere di caricamento della pagina per l'utente che tenta di caricare prima pagina del sito. E 'possibile fare e come? Forse il problema è il modo più corretto per risolverlo?

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
È stato utile?

Soluzione

Sembra che Cross-postato questo sul tornado mailing list qui

Uno dei problemi che si sta funzionando in è che non è possibile avviare l'interno chiamata asincrona di get_current_user, è possibile avviare solo una chiamata asincrona da qualcosa che accade dentro di get o post.

Non ho testato, ma penso che questo dovrebbe farti vicino a quello che state cercando.

#!/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')
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top