DjangoRestFramework【simplejwt认证】

因为如果使用Basic认证,每次用户都输入用户名和密码,如果使用session认证,需要在数据库中生成一张session表,保存session信息,增加了服务器的开销.因此提出了使用jwt认证,jwt认证在服务器存储了加密方式和解密方式,并没有存储任何数据,服务器中对数据进行处理远远高于在数据库中进行处理.
这部分笔记有参考:https://blog.csdn.net/aaaaaaaaanjjj/article/details/122968746

1.安装Simplejwt

pip install djangorestframework-simplejwt

2.配置Simplejwt认证

需要使用的是rest_framework_simplejwt下面authentication.py下面的JWTAuthentication类
DjangoRestFramework【simplejwt认证】_第1张图片
于是将上面的路径复制到settings中

    # 全局认证 优秀级高于视图类中的配置
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # simple-jwt认证
        'rest_framework_simplejwt.authentication.JWTAuthentication'
    ],
    # simplejwt配置, 需要导入datetime模块
	SIMPLE_JWT = {
    # token有效时长
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=30),
    # token刷新后的有效时间
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1),
}

3.添加路由

在我的Django项目的urls代码中:

from django.contrib import admin
from django.urls import path, include
# 引入DRF默认自带的路由
from rest_framework import routers
from shop.views import *
# 引入API文档路由
from rest_framework.documentation import  include_docs_urls

from user.views import UserViewSets
# 引入rest_framework_simplejwt路由
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
    TokenVerifyView
)


router=routers.DefaultRouter()
# 可以通过router默认路由注册资源
router.register('categorys',CategoryViewSets)
router.register('goods',GoodsViewSets)
router.register('users',UserViewSets)
router.register('orders',OrderViewSets)

urlpatterns = [
    path('admin/', admin.site.urls),
    # 配置RESTFulAPI
    path('api/v1/',include(router.urls)),
    # API文档地址
    path('api/v1/docs',include_docs_urls(title="RestFulAPI",description="RestFulAPI v1")),
	
	# rest_framework_simplejwt路由
    # 先通过用户名密码 得到Token Vue将refresh以及access保存>通过access请求服务器 >通过refresh获取新的token
    # 获取Token接口
    path('api/token/',TokenObtainPairView.as_view(),name='login'),
    # 获取Token有效期的接口
    path('api/refresh/',TokenRefreshView.as_view(),name="refresh"),
    # 获取Token的有效性
    path('api/token/verify',TokenVerifyView.as_view(),name="token_verify"),

    # 为了在DRF路由调试界面能够使用用户相关功能需要引入以下路由
    path('',include('rest_framework.urls'))
]

4.测试路由

4.1 测试获取token路由

第一次使用post请求,空参请求http://127.0.0.1:8000/api/token/,则会提示你需要提交账户名和密码:
DjangoRestFramework【simplejwt认证】_第2张图片
则需要在post请求中填写提交的信息:
DjangoRestFramework【simplejwt认证】_第3张图片
提交完用户名和密码之后,则会返回refreshaccess

  • access:这个token就是需要进行认证的标签
  • refresh:access有一段时间的有效期,因此需要refresh生成的token,它的有效时间比较长.

若登入之后访问商品类型,则会提示你需要认证
DjangoRestFramework【simplejwt认证】_第4张图片

此时则需要,将之前登入时候生成的access的token复制过来认证,认证通过之后就可以查询信息了.
DjangoRestFramework【simplejwt认证】_第5张图片

4.2 测试Token有效期接口

过了5分钟之后再去请求category的查询,则此时会显示已经access的请求已经过期,则此时就需要refresh的到的access.
DjangoRestFramework【simplejwt认证】_第6张图片
进入refresh的接口,将前面第一次获取token请求得到的refresh的token复制到refresh请求接口中,得到一个新的accesstoken,将其复制到category请求中的Bearer Token中,则又可以继续请求了.
DjangoRestFramework【simplejwt认证】_第7张图片
此时的请求成功,可以显示所有查询结果:
DjangoRestFramework【simplejwt认证】_第8张图片

5.自定义认证

如果想像百度等这一种web网页,可以实现手机/邮箱/用户名都可以登入,则就需要使用到自定义认证:
DjangoRestFramework【simplejwt认证】_第9张图片

5.1创建自定义类

userapp目录下面创建一个authbackend.py,然后在里面创建一个自定义认证类,继承django.contrib.auth.backends.BaseBackend重写authenticate函数:
原始的只实现用户名密码登入

"""
实现自定义认证类(登入 内容)
如果想自定义认证,就需要继承Django原生的auth,重写django认证方式
"""
from django.contrib.auth.backends import BaseBackend
from user.models import User
from django.db.models import Q


class MyLoginBackend(BaseBackend):
    def authenticate(self, request, **kwargs):
        """
        @param request:
        @param kwargs:认证参数
        @return:如果认证成功返回认证用户 否则返回None
        """
        username=kwargs["username"]
        password=kwargs["password"]

        # 根据用户名查到第一个这个user对象
         user=User.objects.filter(username=username).first()
       
        # 对用户密码进行验证
        b=user.check_password(password)
        if b:
             return user
        else:
             return None

5.2 在setting中配置自定义认证

# 注册自定义认证类 应用名.文件名.认证类名
AUTHENTICATION_BACKENDS=('user.authbackend.MyLoginBackend',)

对应的是MyLoginBackend的路径
DjangoRestFramework【simplejwt认证】_第10张图片

5.3测试

在获取token接口中测试,只要用户名和密码正确,直接就可以返回对应的token
DjangoRestFramework【simplejwt认证】_第11张图片

5.4 使用Q查询实现用户名/邮箱/电话号码多端登入

"""
实现自定义认证类(登入 内容)
如果想自定义认证,就需要继承Django原生的auth,重写django认证方式
"""
from django.contrib.auth.backends import BaseBackend
from user.models import User
from django.db.models import Q


class MyLoginBackend(BaseBackend):
    def authenticate(self, request, **kwargs):
        """
        @param request:
        @param kwargs:认证参数
        @return:如果认证成功返回认证用户 否则返回None
        """
        username=kwargs["username"]
        password=kwargs["password"]
        
        # 使用Q查询,可以连接多个查询语句,在这里可以使用Q查询,先后通过邮箱,电话查询用户信息
        user=User.objects.filter(Q(username=username)|Q(email=username)|Q(mobile=username)).first()
        if user:
            # 对用户密码进行验证
            b=user.check_password(password)
            if b:
                return user
            else:
                return None
        else:
            return None

6.用户认证-自定义控制simpjwt返回内容

这部分类容参考:https://blog.csdn.net/qq_40132294/article/details/125851155
需求:需要返回的响应中包括id,username,token

6.1 查看源码

控制返回值的配置文件在D:\anaconda\envs\Lib\site-packages\rest_framework_simplejwt\settings.py,因此我们只需要重新写一个代码,替代系统自带的方法.
DjangoRestFramework【simplejwt认证】_第12张图片

6.2源码解析

DjangoRestFramework【simplejwt认证】_第13张图片
源码中的序列化类,继承于TokenObtainSerializer序列化类,然后在data字典中添加了refreshaccess两个字段.因此我们想要修改返回值的时候,主要是修改data中的内容.

6.3 自定义返回值序列化类

user\seralizers代码:

class TokenObtainPairSerializer(TokenObtainSerializer):
    token_class = RefreshToken

    def validate(self, attrs):
        data = super().validate(attrs)

        refresh = self.get_token(self.user)

        data["token"] = str(refresh.access_token) #也就是原来的access
        data['user_id'] = str(self.user.id)
        data['user_name'] = str(self.user.username)

        if api_settings.UPDATE_LAST_LOGIN:
            update_last_login(None, self.user)

        return data

代码对比:
DjangoRestFramework【simplejwt认证】_第14张图片

6.4 修改配置文件

修改项目的settings配置文件:

from datetime import timedelta
# simplejwt配置, 需要导入datetime模块
SIMPLE_JWT = {
    # token有效时长
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
    # token刷新后的有效时间
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
    "TOKEN_OBTAIN_SERIALIZER":"user.serializers.TokenObtainPairSerializer"
}

6.5测试

DjangoRestFramework【simplejwt认证】_第15张图片

你可能感兴趣的:(#,Django,Simplejwt认证,Simplejwt自定义认证,自定义控制Simple返回值)