一, 认证规则
全称: JSON web token
解释: 加密字符串的原始数据是 JSON, 后台产生, 通过 Web 传输给前台存储
格式: 三段式 - 头. 载荷. 签名 - 头和载荷才有的是 base64 可逆加密, 签名才有 md5 不可逆加密
内容:
头 (基础信息, 也可以为空): 加密方式, 公司信息, 项目组信息,...
载荷 (核心信息): 用户信息, 过期时间,...
签名 (安全保障): 头加密结果 + 载荷加密结果 + 服务器秘钥 的 md5 加密结果
认证规则:
后台一定要保障 服务器秘钥 的安全性 (它是 jwt 的唯一安全保障)
后台签发 token -> 前台存储 -> 发送需要认证的请求带着 token -> 后台校验得到合法的用户
为什么要有 jwt 认证:
1) 后台不需要存储 token, 只需要存储签发与校验 token 的算法, 效率远远大于后台存储和取出 token 完成校验
2) jwt 算法认证, 更适合服务器集群部署
二, 认证模块
安装: pip install djangorestframework-jwt
模块包: rest_framework_jwt
采用 drf-jwt 框架, 后期任务只需要书写登录
为什么要重写登录: drf-jwt 只完成了账号密码登录, 我们还需要手机登录, 邮箱登录
为什么不需要重写认证类: 因为认证规则已经完成且固定不变, 变得只有认证字符串的前缀, 前缀可以在配置文件中配置
三, JWT 使用
jwt 配置;
在 settings.py 文件中配置, 如果不配置, 默认走 jwt 默认的
在 urls.py 中配置
在 postman 中测试一下签发 token
注意: 上面三个接口都是发送 POST 请求
四, 利用 JWT 实现多方式登录
注: APIResponse 为自定义 Response 对象
- # views.py
- from rest_framework.views import APIView
- from . import models,serializers
- from utils.response import APIResponse
- class LoginAPIView(APIView):
- # 登录接口应该禁用所有的认证和, 权限, 因为不管是谁都应该能进来
- authentication_classes = []
- permission_classes = []
- def post(self, request, *args, **kwargs):
- # 将数据传到序列化组件进行校验
- user_ser = serializers.LoginSerializer(data=request.data)
- user_ser.is_valid(raise_exception=True)
- return APIResponse(msg='login success', data={
- 'username': user_ser.user.username,
- 'token': user_ser.token
- })
- # serializer.py
- from rest_framework.serializers import ModelSerializer, CharField, ValidationError, SerializerMethodField
- from . import models
- from django.contrib.auth import authenticate
- import re
- from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
- class LoginSerializer(ModelSerializer):
- username = CharField(write_only=True)
- password = CharField(write_only=True)
- class Meta:
- model = models.User
- fields = ('username', 'password')
- def validate(self, attrs):
- # user_obj = authenticate(**attrs)
- # if not user_obj:
- # raise ValidationError('用户名或密码错误')
- # 账号密码登录 ==》 多方式登录
- user = self._many_method_login(**attrs)
- # 通过 user 对象生成 payload 载荷
- payload = jwt_payload_handler(user)
- # 通过 payload 签发 token
- token = jwt_encode_handler(payload)
- # 将 user 和 token 存放在序列化对象中, 方便返回到前端去
- self.user = user
- self.token = token
- return attrs
- # 多方式登录 (用户名, 邮箱, 手机号三种方式登录)
- def _many_method_login(self, **attrs):
- username = attrs.get('username')
- password = attrs.get('password')
- # 利用正则匹配判断用户输入的信息
- # 1. 判断邮箱登录
- if re.match(r'.*@.*', username):
- user = models.User.objects.filter(email=username).first() # type: models.User
- # 2. 判断手机号登录
- elif re.match(r'^1[3-9][0-9]{9}$',username):
- user = models.User.objects.filter(mobile=username).first()
- # 3. 用户名登录
- else:
- user = models.User.objects.filter(username=username).first()
- if not user:
- raise ValidationError({'username': '账号有误'})
- if not user.check_password(password):
- raise ValidationError({'password': '密码错误'})
- return user
使用 postman 测试代码:
来源: https://www.cnblogs.com/guapitomjoy/p/11939050.html