2010-05-17 76 views
0

我需要使用來自遠程Auth API的異步回調來編寫身份驗證功能。使用登錄進行簡單身份驗證運行良好,但使用Cookie密鑰進行身份驗證不起作用。它應該檢查cookie中是否存在關鍵字「lp_login」,獲取像異步一樣的API url並執行on_response函數。使用具有異步回調的cookie密鑰進行身份驗證

該代碼幾乎可行,但我看到兩個問題。首先,在on_response函數中,我需要爲每個頁面上的授權用戶設置安全cookie。在代碼中user_id返回正確的ID,但行:self.set_secure_cookie(「用戶」,user_id)不起作用。爲什麼會這樣?

第二個問題。在異步抓取API網址期間,用戶的頁面已經在on_response設置cookie之前加載了關鍵字爲「user」的頁面,並且該頁面將有一個未授權的部分,其中包含登錄或登錄鏈接。這會讓用戶感到困惑。爲了解決這個問題,我可以停止爲試圖加載網站第一頁的用戶加載頁面。是否有可能做到如何?也許問題有更正確的解決方法?

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裏面的異步調用,您可以只啓動發生在getpost內部的異步呼叫。

我沒有測試過它,但我認爲這應該讓你接近你正在尋找的東西。

#!/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') 
相關問題