2010-05-17 5 views
0

Je dois écrire une fonction d'authentification avec un rappel asynchrone à partir de l'API d'authentification distante. L'authentification simple avec connexion fonctionne bien, mais l'autorisation avec la clé cookie ne fonctionne pas. Il devrait vérifier si dans les cookies présents la clé "lp_login", récupérer l'URL de l'API comme async et exécuter la fonction on_response.Authentification à l'aide d'une clé cookie avec rappel asynchrone

Le code fonctionne presque, mais je vois deux problèmes. Tout d'abord, dans la fonction on_response, je dois configurer un cookie sécurisé pour l'utilisateur autorisé sur chaque page. Dans le code, id_utilisateur renvoie l'ID correct, mais la ligne: self.set_secure_cookie ("utilisateur", id_utilisateur) ne fonctionne pas. Pourquoi ça peut être?

Et deuxième problème. Au cours de l'URL de l'API async fetch, la page de l'utilisateur a été chargée avant le cookie d'installation on_response avec la clé "user" et la page contient une section non autorisée avec un lien pour se connecter ou se connecter. Ce sera déroutant pour les utilisateurs. Pour le résoudre, je peux arrêter de charger la page pour l'utilisateur qui essaie de charger la première page du site. Est-il possible de faire et comment? Peut-être que le problème a une façon plus correcte de le résoudre?

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 

Répondre

3

Il vous semble permuté ceci sur la liste de diffusion de tornade here

L'un des problèmes que vous utilisez en est que vous ne pouvez pas lancer l'appel asynchrone à l'intérieur de get_current_user, vous ne pouvez commencer un appel asynchrone de quelque chose qui se passe à l'intérieur de get ou post.

Je ne l'ai pas testé, mais je pense que cela devrait vous rapprocher de ce que vous cherchez.

#!/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') 
Questions connexes