通过项目来深入理解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来调用