2010-05-17 6 views
0

Мне нужно написать функцию аутентификации с асинхронным обратным вызовом из удаленного API Auth. Простая аутентификация с логином работает хорошо, но авторизация с ключом cookie не работает. Он должен проверять, есть ли в файлах cookie ключ «lp_login», получить URL-адрес API, например async, и выполнить функцию on_response.Аутентификация с использованием ключа cookie с асинхронным обратным вызовом

Код почти работает, но я вижу две проблемы. Во-первых, в функции on_response мне нужно настроить безопасный файл cookie для авторизованного пользователя на каждой странице. В коде user_id возвращает правильный идентификатор, но строка: self.set_secure_cookie («user», user_id) не работает. Почему это может быть?

И вторая проблема. В URL-адресе API асинхронной выборки пользовательская страница загрузилась до настройки cookie on_response с ключом «пользователь», и страница будет иметь несанкционированный раздел со ссылкой для входа в систему или входа в систему. Это будет путать пользователей. Чтобы решить эту проблему, я могу остановить загрузку страницы для пользователя, который пытается загрузить первую страницу сайта. Можно ли и как? Может быть, проблема имеет более правильный способ ее решения?

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 

ответ

3

кажется вам перекрестным отправило это в списке рассылки Торнадо here

Одна из проблем, вы работаете в том, что вы не можете запустить асинхронный вызов внутри 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') 

 Смежные вопросы

  • Нет связанных вопросов^_^