Python Tornado集成JSON Web Token方式登录

本项目github地址
前端测试模板如下:

Tornado restful api 项目

项目结构如下:
在这里插入图片描述
项目组织类似于django,由独立的app模块构成。

登录接口设计

模式:post -> /login/
携带参数:{username:"", password:""}
返回:{token: "这里是JWT"}
在这里插入图片描述

Tornado集成JWT

Pyjwt的github地址
首先安装Pyjwt第三方库

$ pip install pyjwt

配置Pyjwt

jwt_expire 单位为秒,图中的表明token7天过期
在这里插入图片描述

接口编写如下

import jwt
class LoginHandler(BaseHandler):
    '''
    用户登录
    post -> /login/
    payload:
        {
            "username": "用户名或者邮箱",
            "password": "密码"
        }
    '''
    async def post(self, *args, **kwargs):
        res = {}

        data = self.request.body.decode("utf-8")
        data = json.loads(data)
        form = LoginForm.from_json(data)
        if form.validate():
            username = form.username.data
            password = form.password.data
            try:
                query = UserProfile.select().where(
                    (UserProfile.username==username) | (UserProfile.email==username)
                )
                user = await self.application.objects.execute(query)
                try:
                    user = user[0]
                except IndexError as e:
                    self.set_status(400)
                    res['non_fields'] = '不存在该用户'
                    self.finish(res)
                    return
                if not user.password.check_password(password):
                    res['non_fields'] = '用户名或密码错误'
                    self.set_status(400)
                else:
                    payload = {
                        'id': user.id,
                        'username': username,
                        'exp': datetime.utcnow()
                    }
                    token = jwt.encode(payload, self.settings["secret_key"], algorithm='HS256')
                    res['token'] = token.decode('utf-8')
                    res['username'] = username
            except UserProfile.DoesNotExist:
                self.set_status(400)
                res['username'] = '用户不存在'

        else:
            self.set_status(400)
            for field in form.errors:
                res[field] = form.errors[field]

        self.finish(res)

关键是这里:

payload = {
    'id': user.id,
    'username': username,
    'exp': datetime.utcnow()
}
token = jwt.encode(payload, self.settings["secret_key"], algorithm='HS256')
res['token'] = token.decode('utf-8')
res['username'] = username

用HS256加密算法和自己的私钥来加密payload转换成token并返回。

测试接口:

在这里插入图片描述

成功返回数据!以后再访问需要登录的页面时,在请求头(request header)中加入这个字段就可以了!
在这里插入图片描述

原文地址:https://www.cnblogs.com/PyKK2019/p/10759479.html