使用具有异步回调的cookie密钥进行身份验证

问题描述:

我需要使用来自远程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 

看来你跨张贴这龙卷风邮件列表上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')