JWT 介绍
JWT( Json Web Tokens ),是一种开发的行业标准 RFC 7519 ,用于安全的表示双方之间的声明。目前,jwt广泛应用在系统的用户认证方面,特别是现在前后端分离项目。
JWT认证流程
在项目开发中,一般会按照给定流程进行认证,即:用户登录成功之后,服务端给用户浏览器返回一个 token,以后用户浏览器要携带 token 再去向服务端发送请求,服务端校验 token 的合法性,合法则给用户看数据,否则,返回一些错误信息。
传统Token方式和JWT在认证方面有什么差异?
传统 token 方式
:
用户登录成功后,服务端生成一个随机 token 给用户,并且在服务端(数据库或缓存)中保存一份 token,以后用户再来访问时需携带 token,服务端接收到 token 之后,去数据库或缓存中进行校验 token 的是否超时、是否合法。
jwt 方式
:
用户登录成功后,服务端通过 jwt 生成一个随机 token 给用户(服务端无需保留 token),以后用户再来访问时需携带token,服务端接收到 token 之后,通过 jwt 对 token 进行校验是否超时、是否合法。
安装
pip install PyJWT
eg
1.model.py -- 生成数据模型
from datetime import datetime
from msilib.schema import tables
from django.db import models
# Create your models here.
##### 管理后台用户表数据
class AdminUsers(models.Model):
class Meta:
db_table="crm_admin_users"
username=models.CharField("用户名",max_length=30,unique=True)
password=models.CharField("密码",max_length=32)
profile_picture=models.CharField("头像",max_length=200,default="",null=True)
mg_status = models.BooleanField("状态",choices=((0,'关闭'),(1,'启用')),default=1)
email = models.EmailField("邮箱地址",null=True,default="")
token = models.CharField("token值",max_length=150,default="",null=True,unique=True)
expired_at = models.IntegerField("过期时间")
roles = models.ManyToManyField("Roles")### 用户和角色多对多
depart=models.ManyToManyField("Department") ### 用户和部门多对多关系
created_at = models.DateTimeField('创建时间',default=datetime.now,null=True)
updated_at = models.DateTimeField("更新时间",default=datetime.now,null=True)
#### 部门表的内容
class Department(models.Model):
class Meta:
db_table="crm_department"
pid=models.IntegerField("部门父id")
name=models.CharField("部门名称",max_length=50,default="",null=True)
status = models.BooleanField("状态",choices=((0,'停用'),(1,'启用')),default=1)
order=models.IntegerField("排序")
created_at = models.DateTimeField('创建时间',default=datetime.now,null=True)
updated_at = models.DateTimeField("更新时间",default=datetime.now,null=True)
####角色列表
class Roles(models.Model):
class Meta:
db_table="crm_roles"
role_name=models.CharField("角色名称",max_length=20,default="")
role_desc = models.CharField("角色描述",max_length=50,default="")
created_at = models.DateTimeField('创建时间',default=datetime.now,null=True)
updated_at = models.DateTimeField("更新时间",default=datetime.now,null=True)
##### 权限表
class Permissions(models.Model):
class Meta:
db_table="crm_permissions"
pid = models.IntegerField("父级id",default=0)
name = models.CharField("权限名称",max_length=20,default="")
path = models.CharField("路由地址",max_length=40,default="")
is_menu = models.SmallIntegerField("是否菜单",choices=((1,"是"),(2,"否")),default=1)
icon = models.CharField("菜单图标",max_length=30,default="",null=True)
sort = models.IntegerField("排序",default=10)
access=models.CharField("权限标识",max_length=50,default="",null=True)
roles=models.ManyToManyField("roles") ### 角色和权限多对多的关系
created_at = models.DateTimeField('创建时间',default=datetime.now,null=True)
updated_at = models.DateTimeField("更新时间",default=datetime.now,null=True)
2. 在 view.py -- 文件中生成token。
import jwt
import time
# 生成 token: jwt.encode(playload, key, algorithm='HS256')
# playload : 配置参数; key为app的SECRET_KEY(密钥); algorithm 为加密算法
info = {
'exp': time.time() + 30000, # jwt的过期时间,这个过期时间必须要大于签发时间
'iat': time.time(), # jwt的签发时间
'iss': 'IsSuer', # jwt签发者
'data': {
'username': "shijieheping",
'timestamp': time.time()
}
}
jwt_encode = jwt.encode(info, "secret", algorithm="HS256")
# 解密,校验签名
s = jwt.decode(s, 'secret', issuer='lianzong', algorithms=['IsSuer'])
3.新建electronicAdmin/middleware.py文件 (settings.py 同级目录); 将 token 进行认证。
#### 自定义中间件的请求
import time
from django.utils.deprecation import MiddlewareMixin;#### 导入包文件
from django.http import JsonResponse;
from .models import *
# 定义中间件的类方法
class Authorization(MiddlewareMixin):
# 前置拦截器,请求前触发的方法
def process_request(self,request):
print("中间件触发")
try:
# 判断请求的如果不是登录的Api接口,判断token的内容
if ('login' not in request.path):
# 获取token值
token = request.META.get("HTTP_AUTHORIZATION")
# 没有传递token值
if not token:
return JsonResponse({
'code':401,
'msg':'token无效'
})
# 通过token值获取用户的信息,判断token是否合理
user = AdminUsers.objects.filter(token=token).first()
print(user)
# 没有token值
if not user:
return JsonResponse({
'code':401,
'msg':'token不存在'
})
# 判断用户的时间是否过期
if user.expired_at < time.time():
return JsonResponse({
'code':401,
'msg':'token已经过期'
})
except Exception:
return JsonResponse({
'code':401,
'msg':'token无效'
})
settings.py 注册中间件
MIDDLEWARE = [
'electronicAdmin.middleware.MD1'
]