drf之jwt认证

JWT认证规则

全称:json web token
解释:加密字符串的原始数据是json,后台产生,通过web传输给前台存储
格式:三段式 - 头.载荷.签名 - 头和载荷用的是base64可逆加密,签名用md5不可逆加密
内容:
头(基础信息,也可以为空):加密方式、公司信息、项目组信息、…
载荷(核心信息):用户信息、过期时间、…
签名(安全保障):头加密结果+载荷加密结果+服务器秘钥 的md5加密结果

认证规则:
后台一定要保障 服务器秘钥 的安全性(它是jwt的唯一安全保障)
后台签发token(login接口 ) -> 前台存储 -> 发送需要认证的请求带着token -> 后台校验得到合法的用户 -> 权限管理

为什么要有jwt认证:
1)服务器压力小, 后台不需要存储token,只需要存储签发与校验token的算法,效率远远大于后台存储和取出token完成校验
2) jwt算法认证,更适合服务器集群部署

默认已创建好drf框架,没有创建可以参考 快速搭建django-rest framework项目

一、安装

安装:pip install djangorestframework-jwt
模块包:rest_framework_jwt

采用drf-jwt框架,后期任务只需要书写登录
为什么要重写登录:drf-jwt只完成了账号密码登录,我们还需要手机登录,邮箱登录
为什么不需要重写认证类:因为认证规则已经完成且固定不变,变得只有认证字符串的前缀,前缀可以在配置文件中配置

二、配置

REST_FRAMEWORK = {
  	# 默认 jwt 处理方式 
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}

import datetime
JWT_AUTH = {
  	# 过期时间 
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    # 允许刷新
    'JWT_ALLOW_REFRESH': True,
    # 刷新的过期时间
    'JWT_REFRESH_EXOIRATION_DELTA': datetime.timedelta(days=7),
	'JWT_AUTH_HEADER_PREFIX': 'JWT',
}

三、使用

1.在url中配置

from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token,verify_jwt_token,refresh_jwt_token

urlpatterns = [
    # 签发token
    path('login/$',obtain_jwt_token),
    # 校验token
    path('verify/$',verify_jwt_token),
    # 刷新token
    path('refresh/$',refresh_jwt_token),
]

启动项目,在postman中测试一下token签发

在这里插入图片描述

2.利用JWT实现多方式登录

  1. views.py
from django.http import JsonResponse
# Create your views here.
from rest_framework.views import APIView
from . import models, serializers


class LoginAPIView(APIView):
    # 登录接口应该禁用所有的认证和、权限,因为不管是谁都应该能进来
    permission_classes =()
    authentication_classes = ()

    def post(self, request, *args, **kwargs):
        # 将数据传到序列化组件进行校验
        user_ser = serializers.LoginSerializer(data=request.data)
        user_ser.is_valid(raise_exception=True)

        return JsonResponse({'msg':'login success', 'data':{
            'username': user_ser.user.username,
            'token': user_ser.token
        }})

serializers.py

from django.contrib.auth.models import User
from rest_framework.serializers import ModelSerializer, CharField, ValidationError, SerializerMethodField
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 = 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 = User.objects.filter(email=username).first()  # type: User
        # 2.判断手机号登录
        elif re.match(r'^1[3-9][0-9]{9}$', username):
            user = User.objects.filter(mobile=username).first()
        # 3.用户名登录
        else:
            user = User.objects.filter(username=username).first()

        if not user:
            raise ValidationError({'username': '账号有误'})

        if not user.check_password(password):
            raise ValidationError({'password': '密码错误'})

        return user

urls.py

from django.contrib import admin
from django.urls import path,include
from rest_framework_jwt.views import obtain_jwt_token,verify_jwt_token,refresh_jwt_token
from .views import LoginAPIView
urlpatterns = [
    path('admin/', admin.site.urls),
    # 签发token
    path('login/', LoginAPIView.as_view()),
    # 校验token
    path('verify/', verify_jwt_token),
    # 刷新token
    path('refresh/', refresh_jwt_token),
]

使用postman验证:
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值