JWT认证
工作原理
1)jwt = base64(头部).base(载荷).hash256(base64(头部).base(载荷).密钥)
2) base64是可逆算法、hash256是不可逆算法
3)密钥是固定的字符串,保存在服务器
'''
1) 服务器不要存储token, token 交个每一个客户端来存储
2)服务器存储的是 签发和校验token 两段算法,签发认证效率高
3)算法完成各集群服务器同步低,路由项目完成集群部署(适应高并发)
'''
格式
'''
1) jwt token 采用三段式: abc(头部).123(载荷).xyz(签名)
2)没一部分都是一个json字典加密形成的字符串
3)头部和载荷采用的是base64可逆加密(前台和后台都可以解密)
4)签名采用的是hash256不可逆加密(后台校验采用碰撞校验)
5)各部分字典的内容:
头部:基础信息 - 公司信息、项目组信息、可逆加密采用的算法
载荷:有用单非私密的信息 - 用户可公开信息、过期时间
签名:头部+载荷+密钥 不可逆加密后的结果
注: 服务器jwt签名加密密钥一定不能泄露
签发token:固定的头部信息加密、当前的登录用户与过期时间加密.头部+载荷+密钥生成不可逆加密
校验token: 头部可校验可不校验,载荷校验出用户与过期时间,头部+载荷+密钥完成碰撞检测校验token是否被篡改
'''
drf-jwt
安装
pip install djangorestframework-jwt
手动签发token
# 1) 通过 username 和 password得到user对象
# 2) 通过user对象生成payload: jwt_payload_handler(user) => payload
# from rest_framework_jwt.serializers import jwt_payload_handler
# 3) 通过payload 签发token: jwt_encode_handler(payload) => token
# from rest_framework_jwt.serializers imiport jwt_encode_handler
手动校验token
serializers
import re
from rest_framework import serializers
from .models import User
from rest_framework_jwt.serializers import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
class UserModelSerializer(serializers.ModelSerializer):
# 自定义反序列化字段
usr = serializers.CharField(write_only=True)
pwd = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ['usr', 'pwd']
extra_kwargs = {
}
def validate_usr(self, value):
return value
def validate_pwd(self, value):
return value
def validate(self, attrs):
usr = attrs.get('usr')
pwd = attrs.get('pwd')
if re.match('.*@.*', attrs['usr']):
user = User.objects.filter(email=usr).first()
elif re.match('1[3-9][0-9]{9}', usr):
user = User.objects.filter(mobile=usr).first()
else:
user = User.objects.filter(username=usr).first()
if user and user.check_password(pwd):
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
self.user = user
self.token = token
return attrs
raise serializers.ValidationError({'data': '数据有误'})
views.py
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, CreateModelMixin
from utils.response import APIResponse
from . import models, serializer
# 实现多方式登录签发token:账号、手机号、邮箱 登录
# 1) 禁用认证与权限组件
# 2) 拿到前台登录信息
# 3) 校验得到登录用户
# 4) 签发token并返回
class LoginAPIView(APIView):
authentication_classes = []
permission_classes = []
def post(self, request, *args, **kwargs):
user_ser = serializer.UserModelSerializer(data=request.data)
user_ser.is_valid(raise_exception=True)
return APIResponse(token=user_ser.token, results=serializer.UserModelSerializer(user_ser.user).data)