tornado后端session用户认证鉴权解决方案
    
  
      
      
     
    
      
        tornado框架自身没有集成session鉴权,但是对cookie支持良好。由于现在前端vue部署在一个端口上,后端tornado分布式应用部署在多个端口上,这就会导致浏览器的跨域问题产生(url不同,即协议,域名,端口三者有不相同的地方)。
在前后端分离的项目中,由于页面的路由跳转由vue控制,后端应用只提供数据。这样就会使鉴权任务变得较为复杂。一个比较良好的解决思路是,在前端需要鉴权才能访问的路由中添加一个后端异步请求,该请求用来判断用户是否登录,这样来判断用户当前是否有权限访问该页面。同时,后端需要    登录才能访问的接口,用修饰器来判断用户当前是否登录。下面提供一种tornado实现session的解决方案。
在新建一个HTTP请求时,需要初始化一个session类,该类应该实现以下功能:
能够从请求头的cookie中得到session_id;
 
能够生成一个全新的session_id,并将其返回给client;
 
若server得到的session_id失效,则清空client的cookie;
 
若server得到的sess_id有效,则从redis中取出对应的用户信息
 
在一个HTTP请求结束时,需要判断,当前这个链接是否为”登录成功“的API,如果是,则需要将对应的用户信息存储到redis中,并生成一个新的session_id返回给用户。
代码如下:
BaseHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   |  class BaseHandler(web.RequestHandler):     def initialize(self):         self.session_save_tag = False         self.session = None
      async def prepare(self):         await self.init_session()         if get_config().session['session_key_name'] in self.session:             self.current_user = LoginUser(self.session[get_config().session['session_key_name']])     def on_finish(self):         if self.session is not None and self.session_save_tag:             get_loop().add_callback(self.session.save)         get_logger().info("[一次HTTP请求结束]")         async def init_session(self):         if not self.session:             self.session = Session(self)             await self.session.init_fetch()                  def save_session(self):         self.session_save_tag = True         self.session.generate_session_id()         get_logger().info("【登录】生成session_id结束")
      def save_login_user(self, user: dict):         login_user = LoginUser(None)         login_user['username'] = user.get("username", "")         login_user['email'] = user.get("email", "")         login_user['phone'] = user.get("phone", "")         self.session[get_config().session['session_key_name']] = login_user         self.current_user = login_user         self.save_session()
 
  | 
 
login API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   |  class LoginHandler(BaseHandler):     async def post(self):         try:             username = self.data['username']             password = self.data['password']             doc_user = await get_one_data(self.mongodb_manager, Config.mongodb_config['user_info'],                                           {'username': username})             print(doc_user)             if doc_user is not None and password == doc_user['password']:                 self.save_login_user(doc_user)                 get_logger().info("登录成功,用户信息已经保存")         except Exception as e:             error = traceback.format_exc()             get_logger().error("login fail[{}]:{}".format(e, error))
 
  |