Pregunta

Tengo que escribir la función de autenticación con devolución de llamada asincrónica de la API de autenticación remota. autenticación simple con entrada está funcionando bien, pero la autorización con llave galleta, no funciona. Debe comprueba si en las cookies clave actual "lp_login", ir a buscar url API como asíncrono y ejecutar on_response función.

El código casi funciona, pero veo dos problemas. En primer lugar, en función de on_response Necesito fijar galleta segura para el usuario autorizado en cada página. En el código user_id devuelve correcto ID, pero la línea: self.set_secure_cookie ( "usuario", user_id) trabajo does't. Por qué puede ser?

Y segundo problema. Durante asíncrono ha podido recuperar la URL de la API, la página de usuario ha cargado antes de galletas configuración on_response con la tecla "usuario" y la voluntad página tiene una sección no autorizada con enlace a usuario o iniciar la sesión. Será confuso para los usuarios. Para resolverlo, puedo dejar de carga de las páginas de usuario que al intentar cargar la primera página del sitio web. ¿Es posible hacer y cómo? Tal vez el problema tiene forma más correcta para resolverlo?

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
¿Fue útil?

Solución

Parece que Cruz-registrado esta en la lista de correo tornado aquí

Uno de los problemas que se están ejecutando en es que no se puede iniciar el interior de la llamada asincrónica get_current_user, sólo se puede iniciar una llamada asincrónica de algo que sucede en el interior de get o post.

No he probado, pero creo que esto se debe conseguir que cerca de lo que busca.

#!/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')
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top