美文网首页Tornado
Tornado学习笔记第六篇-集成JWT到Tornado中

Tornado学习笔记第六篇-集成JWT到Tornado中

作者: 码农小杨 | 来源:发表于2020-02-28 17:35 被阅读0次

    Json Web Token是解决现在前后端分离权限验证的方法之一。

    先看几篇参考文章:

    前后端分离之JWT用户认证

    JWT -- 理论介绍、实战、问题

    JWT的过期机制

    在使用session机制的时候,session的本质是在服务器中生成的一段随机字符串,在Tornado的单体应用中我们可以使用set_cookieset_secure_cookie通过浏览器将session保存到浏览器的cookie中。因为这个步操作是交给浏览器做的,因此前后端分离的情况的时候,这两个方法就是没用的了。不过,我们可以通过接口将session返回给前端,前端下次查询接口带上session也是可以完成前后端分离,我们在后端可以拦截session获取到保存到session中的信息。例如使用itsdangerous来进行加密。

    JWT的本质是加密技术,我们在服务器加密生成字符串返回给客户端,客户端保存,下次查询的之后携带上来,服务端进行校验。相比于sesssion保存在服务器,JWT是不用保存的。

    下面我们看如何在Tornado中集成JWT,我们以慕课网实战课程为例。

    我们使用的模块是pyjwt

    生成加密字符串

    # 构建 json web token
    # 设置过期时间要设置 UTC 时间 因为内部检查使用的也是 UTC 时间
    payload = {
        "id": user.id,
        "nick_name": user.nick_name,
        "exp": datetime.utcnow()
    }
    token = jwt.encode(payload, self.settings["secret_key"], algorithm='HS256')
    re_data["token"] = token
    

    我们将用户的idnick_name设置在payload中。

    那把这个加密字符串返回给前端之后 怎么使用呢?这就是要我们重新抒写权限装饰器然后使用这个token了。

    下面是我们要改写的装饰器。

    def authenticated_async(method):
        @functools.wraps(method)
        async def wrapper(self, *args, **kwargs):
            tsessionid = self.request.headers.get("tsessionid", None)
            if tsessionid:
    
                # 对token过期进行异常捕捉
                try:
    
                    # 从 token 中获得我们之前存进 payload 的用户id
                    send_data = jwt.decode(tsessionid, self.settings["secret_key"], leeway=self.settings["jwt_expire"],
                                           options={"verify_exp": True})
                    user_id = send_data["id"]
    
                    # 从数据库中获取到user并设置给_current_user
                    try:
                        user = await self.application.objects.get(User, id=user_id)
                        self._current_user = user
    
                        # 此处需要使用协程方式执行 因为需要装饰的是一个协程
                        await method(self, *args, **kwargs)
    
                    except User.DoesNotExist as e:
                        self.set_status(401)
    
                except jwt.ExpiredSignatureError as e:
                    self.set_status(401)
            else:
                self.set_status(401)
            self.finish({})
    
        return wrapper
    

    上面展示了如何使用我们的jwt

    在需要权限的地方使用了权限装饰器即可。

    class GroupHandler(RedisHandler):
    
        @authenticated_async
        async def get(self, *args, **kwargs):
    

    总体使用感觉在Flask中集成itsdangerous库很类似。

    相关文章

      网友评论

        本文标题:Tornado学习笔记第六篇-集成JWT到Tornado中

        本文链接:https://www.haomeiwen.com/subject/tcolhhtx.html