通过项目来深入理解tornado(六):重写authenticated装饰器

通过项目来深入理解tornado(六):重写authenticated装饰器

前言

之前完成了登录注册功能,有一个新的问题也随之而来

因为采用的是jwt的模式,所以没用到seesion,那么如果有一个页面需要用户登录怎么办呢

其实如果使用原来的seesion模式的话,tornado是提供了一个装饰器的

就是authenticated,在tornaodo.web里面

这个装饰器逻辑其实比较简单,就是去获取self._current_user

如果获取不到就直接跳转到登录页面,前提是你需要在setting里设置了login_url

那么如何重写呢

先看代码,后面一一解释

import functools
import jwt
from apps.users.models import User


def authenticated(method):
    @functools.wraps(method)
    async def wrapper(self, *args, **kwargs):
        jwt_token = self.request.headers.get('jwt_token', None)
        if jwt_token is not None:
            try:
                token = jwt.decode(jwt_token, self.settings['secret_key'], algorithm='HS256', leeway=7*24*3600, options={'verify_exp':True})
                #取出用户
                try:
                    user = await self.application.objects.get(User, id=token['id'])
                    # 一定要设置_current_user = user ,并且注意前面有下划线
                    self._current_user = user
                    await method(self, *args, **kwargs)
                except User.DoesNotExist:
                    self.set_status(401)

            except jwt.ExpiredSignatureError:
                self.set_status(401)
        else:
            self.set_status(401)
        self.finsh()
    return wrapper

  这个需要前端的配合,设置相对应的字段进headers里

首先先获取jwt_token,如果获取不到,抛异常,如果获取到,再用我们的密钥进行解密,

解密失败,抛异常,如果解密成功,取出里面的user_id,并且通过协程的方式去数据库取出该用户并且设置到self._current_user里

注意前面有下划线,最后运行被装饰的函数,注意因为装饰的函数是协程,所以需要用await的方式来调用

还有一个小点需要注意一下

token = jwt.decode(jwt_token, self.settings['secret_key'], algorithm='HS256', leeway=7*24*3600, options={'verify_exp':True})

  这里的leeway代表的是过期时间,因为前端的jwt里面设置了exp字段为datetime.utcnow(),相当于在exp字段后加上这个设置的时间,然后options代表验证这个字段。

 

总结:

1.jwt.decode()这个方法的过期时间的设置,需要leeway和options

2.取到用户后一定要设置self._current_user

3.被装饰的方法如果是协程的话需要用await来调用

 

posted @ 2018-11-27 13:56  __Miracle  阅读(699)  评论(0编辑  收藏  举报