首页 > 编程语言 >drf - 过滤、排序、异常源码剖析、jwt

drf - 过滤、排序、异常源码剖析、jwt

时间:2023-09-10 10:33:58浏览次数:43  
标签:jwt self queryset request 接口 token 源码 drf

过滤类的源码剖析

1、为什么在视图类中配置了一个过滤类,就可以走?
	  -filter_backends = [SearchFilter,MyFilter]
2、前提条件是必须继承在视图类中继承GenericAPIView:
	  因为filter_backends是GenericAPIView的类属性。
3、如果光继承了GenericAPIView还是不行,还需要再继承ListModelMixin,因为过滤是在ListModelMixin中做的。
当我的程序来到:
            def list(self, request, *args, **kwargs):
                queryset = self.filter_queryset(self.get_queryset())
-我list方法中没有这个方法,最终就会找到我GenericAPIView中的filter_queryset方法:
    def filter_queryset(self, queryset):
        # 将我视图类中的filter_backends先强转成一个列表,然后for循环
        for backend in list(self.filter_backends):
            # 再实例化我这个过滤类,调用里面的filter_queryset方法得到一个对象,再将对象返回出去
            queryset = backend().filter_queryset(self.request, queryset, self)
            return queryset

分页类的源码剖析

1.1、视图类中配置了分页类,为什么就有分页了?
	 - pagination_class = CommonCursorPagination  # GenericAPIView类属性
如果光继承了GenericAPIView还是不行,还需要再继承ListModelMixin,因为分页是在ListModelMixin中做的。
当我的程序来到:
    def list(self, request, *args, **kwargs):
        # 过滤开始
        queryset = self.filter_queryset(self.get_queryset())
        
#######################分页开始#######################
		# 当程序走到这里就会调用paginate_queryset方法,但是这个方法List类中没有,最终会找到GenericAPIView中
        page = self.paginate_queryset(queryset)
        if page is not None: # 如果return None就不做分页
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
#######################分页结束#######################
        
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
    
GenericAPIView中的paginate_queryset方法:
    def paginate_queryset(self, queryset):
        # 调用下面的paginator的方法,得到一个None或者一个分页类
        if self.paginator is None:
            return None
        # 得到一个分页类就会调用该类里面的paginate_queryset方法,完成分页
        return self.paginator.paginate_queryset(queryset, self.request, view=self)
 
    -self.paginator 方法包装成了属性,就是分页类的对象  CommonCursorPagination()
    @property
    def paginator(self):
        self._paginator = self.pagination_class() # 咱们配置的分页类  CommonCursorPagination
        return self._paginator
    - 调用了 分页类对象的paginate_queryset--->完成真正的分页
    	分页类对象.paginate_queryset(queryset, self.request, view=self)

异常的源码剖析

为什么在配置文件中配置了自己写的全局异常处理函数,只要出了异常,它就会走?
	-APIView执行流程---》dispatch的 
    	try:
        except Exception as exc:
            # 执行handle_exception方法
            response = self.handle_exception(exc) # exc看这里,exc是错误对象
            
            -self.handle_exception(exc):# 执行我视图类中的handle_exception
            
        def handle_exception(self, exc):
            exception_handler = self.get_exception_handler() # 拿到的就是配置文件中配的那个函数
            response = exception_handler(exc, context) #执行这个函数,传了俩参数
            return response
        
        -self.get_exception_handler()是如何从配置文件中拿出来的
        -self.settings.EXCEPTION_HANDLER  # 先从项目配置文件中找:key为它的EXCEPTION_HANDLER,如果项目配置文件没有,拿drf内置的配置文件


        # 如果你写了全局异常处理函数,配置好了,但是前端还没有返回固定格式,可能的原因是什么?
        -1 这个错误不是在三大认证和视图类的方法中产生的,之前产生的--》中间件,包装新的request
        -2 你写的common_exception执行出错了

接口文档

作用:
	让前端知道我每个接口的用途,所以我们需要写一个接口文档来供前端使用
    
接口文档的展现形式:
    1、word、.md
    2、自动生成接口文档------>后端通过配置----->把所有接口都自动生成----->地址---->访问这个地址就可以看到所有接口
    3、公司内部搭建接口文档平台:
        - 开源:Yapi--->同学搭建一个,给搭建用
            -https://zhuanlan.zhihu.com/p/366025001
        - 自己开发(自研)
        
    4 使用第三方平台(花钱)-->showdoc
    
接口文档该如何写:
	以用户注册为例:
        1、接口描述
        2、请求地址
        3、请求方式
        4、编码格式:json、urlencoded、form-data
        5 请求参数:参数详解
            -请求地址参数
            -请求体参数
        6 返回格式示例--》返回参数说明
        7 备注(可有可无)--》错误码
        
自定生成接口文档:
    1、pip install coreapi
    2、设置接口文档访问路径:
    from rest_framework.documentation import include_docs_urls
    urlpatterns = [
        path('docs/', include_docs_urls(title='站点页面标题'))
    ]
    3、在视图中加注释
    4、配置文件中配置:
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'

jwt介绍和构成(理论)

# 做会话保持的发展历史
	-https://www.cnblogs.com/liuqingzheng/p/8990027.html

# jwt:Json Web Token:web方向的token认证方案
# 在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证(token串)。我们不再使用Session认证机制,而使用Json Web Token(本质就是token)认证机制

# Json web token (JWT), JWT用在咱们前后端做登录认证的,如果登录了,就携带token过来,如果没登录,就不携带---》后端通过验证token的准确性,确定是谁访问我们


#JWT的构成--三部分
	eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
    
    # 头:header
    	-一般放公司信息,加密方式(没放秘钥)
    # 荷载:payload
    	-当前用户的信息:用户名,用户id,token过期时间。。。
    # 签名:signature
    	-第一部分和第二部分通过加密得到的字符串

jwt的签发与认证

以后使用jwt,最核心的就两个地方
	-签发:(登录接口)
        -登录接口、登录成功、签发token(三段式)
        -header,用base64编码,暂放
        {"company": "公司信息",}
        -payload,用base64编码,暂放
        {用户名,用户权限,过期时间}
        -使用加密方式:md5,把header和payload 都update进md5中--->生成前面--->base64编码
        -三段拼接起来---》用 .  分割 
        
    -认证:(认证类)
        -用户携带token过来,认证
        -取出第一部分的token
        -取出第二段的payload
        -使用之前同样的加密算法(密码),得到前面的
        -跟token的第三部分比较,如果一样的话,表示没有被修改,顺利执行下去,返回两个值
        -如果被修改了抛出异常

base64编码

作用:
    1、token串使用的就是base64编码格式
    2、互联网中前后端数据交互,可以使用base64编码
    3、图片二进制可以使用base64编码传递
    
介绍:
	Base64编码是一种将二进制数据转换为可打印ASCII字符的编码方式。它常用于在网络传输中传递二进制数据,或者在文本协议中嵌入二进制数据。

注意事项:
	需要注意的是,base64.b64encode和base64.b64decode函数的参数和返回值都是字节串(bytes类型),而不是字符串(str类型)

使用方法

import json
import base64

d = {'name': "杨赋华", 'age': 18, "gender": "男"}

#######编码
d_json = json.dumps(d)
# 注意使用base64加密必须是字节类型,所以一定要encode一下
d_base = base64.b64encode(d_json.encode("utf-8"))
print(d_base)
# b'eyJuYW1lIjogIlx1Njc2OFx1OGQ0Ylx1NTM0ZSIsICJhZ2UiOiAxOCwgImdlbmRlciI6ICJcdTc1MzcifQ==' 这就是一个标准的base64编码

#######解码
d_base_decode = base64.b64decode(d_base)
print(json.loads(d_base_decode))
# {'name': '杨赋华', 'age': 18, 'gender': '男'}

drf-jwt的介绍

# django 中使用jwt

# 可以自己写,使用第三方
	-django-rest-framework-jwt:有点老
    -djangorestframework-simplejwt:新的
    -自己写:								https://gitee.com/liuqingzheng/rbac_manager/blob/master/libs/lqz_jwt/token.py
    
# 下载:
pip install djangorestframework-jwt

django-rest-framework-jwt快速使用

签发:
	默认是在auth_user表中签发 ------>登录接口------>内部已经封装好了
    
路由层:
    rom rest_framework_jwt.views import obtain_jwt_token
    urlpatterns = [
        path('login/', obtain_jwt_token),
    ] # obtain_jwt_token登录接口
    
# 在auth_user中添加一条数据,post访问改地址,就会得到一个token串

局部认证:
	from rest_framework_jwt.authentication import JSONWebTokenAuthentication
    class Publish(ViewSetMixin, ListAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializers
        authentication_classes = [JSONWebTokenAuthentication]
        # 问题:配置了登录才可以访问该接口,但是不起作用,还是可以直接访问该接口,所以还需要配合权限类使用
权限:
	from rest_framework.permissions import IsAuthenticated
	permission_classes = [IsAuthenticated]
	-IsAuthenticated源码解析:
    class IsAuthenticated(BasePermission):
        def has_permission(self, request, view):
            # 如果都为True权限通过
            return bool(request.user and request.user.is_authenticated)
默认认证类:带了token过来,它会校验,不带,就不校验------>不校验,request.user就没有值------>使用IsAuthenticated类做限制
前端固定写法
Authorization:jwt 中间要空一格eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InlhbmciLCJleHAiOjE2OTQyMzczNjMsImVtYWlsIjoiMTIzQHFxLmNvbSJ9.tsBOxloMlKtA6kDKANxZemDX2BzTRTYZHCa6Gey_vGM

定制签发返回格式

# 自定义认证返回结果

# 写个函数
def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'status': 100,
        'msg': '登录成功',
        'token': token,
        'username': user.username
    }

# 配置文件配置
JWT_AUTH = {
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.response.jwt_response_payload_handler',
}

源码分析

为什么 路由这样配了,就会有个登录接口?
	path('login/', obtain_jwt_token), # obtain_jwt_token  
    # obtain_jwt_token = ObtainJSONWebToken.as_view()
ObtainJSONWebToken源码:
	class ObtainJSONWebToken(JSONWebTokenAPIView):
        # 这里面就写了一个序列化类
        serializer_class = JSONWebTokenSerializer
        
JSONWebTokenAPIView源码:# 这里面写了一个登录接口
class JSONWebTokenAPIView(APIView):
    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            user = serializer.object.get('user') or request.user
            token = serializer.object.get('token')
            response_data = jwt_response_payload_handler(token, user, request)
            response = Response(response_data)
            if api_settings.JWT_AUTH_COOKIE:
                expiration = (datetime.utcnow() +
                              api_settings.JWT_EXPIRATION_DELTA)
                response.set_cookie(api_settings.JWT_AUTH_COOKIE,
                                    token,
                                    expires=expiration,
                                    httponly=True)
                return response
    # 在父类中:JSONWebTokenAPIView  post
	-登录走的是JSONWebTokenAPIView的post,签发token 是在序列化类中
    -签发完token执行了,咱们写的jwt_response_payload_handler,所以才能定制返回格式

作业

# 1 自己封装一个jwt的签发和认证
# 2 用一下 yapi,showdoc

------
# 3 自定义用户表,使用djagno-jwt去签发(登录接口)和认证(认证类)

标签:jwt,self,queryset,request,接口,token,源码,drf
From: https://www.cnblogs.com/chao0308/p/17690860.html

相关文章

  • drf- 过滤、排序、异常处理
    session的执行流程写一个登录接口----->保存用户的登录状态 -获取到用户名,密码-使用request.session["username"]=用户名、或者request.session["pk"]=pk值-签发阶段做了三件事: -1、生成一个随机的字符串-2、在django_session表中保存 -se......
  • drf- 三大认证、排序
    三大认证组件登录认证我们可以使用auth自带的User表,也可以选择自定义表.写登录接口,登录成功要有标志,生成一个随机的字符串,放到表中,以后只要携带这个字符串就可以登录成功。视图层方法一:classUserView(GenericViewSet):queryset=models.UserInfo.objects.all()......
  • flink kerberos认证源码剖析
    文章目录01引言02flink的安全机制03源码流程分析3.1程序入口3.2安全模块安装3.3模块安装源码04文末01引言官方的文档:https://nightlies.apache.org/flink/flink-docs-master/docs/deployment/security/security-kerberos/我们都知道,如果某个大数据组件(如:hadoop、flink等)......
  • 基于web的图书馆管理系统设计与实现-计算机毕业设计源码+LW文档
    1.1选题背景信息技术的发展改变了我们的生活方式,许多行业的管理模式发生了根本性改变,特别是零售业受到电子商务强烈的冲击,越来越多的人参与到网购中。许多传统行业逐渐凋零,蓬勃发展的信息技术带来了大量的数据,通过数据可以获取到许多隐藏在背后的发展机遇。而这些数据都是存储在数......
  • 开源药店商城系统源码比较:哪个适合你的药品电商业务
    在构建药品电商业务时,选择适合的药店商城系统源码是至关重要的决策之一。开源药店商城系统源码提供了快速入门的机会,但在选择之前,您需要仔细考虑您的需求、技术要求和可扩展性。本文将比较几个流行的开源药店商城系统源码,以帮助您找到最适合您业务的选项。1.MagentoMagento是一个......
  • 一套基于spring boot vue开发的UWB定位系统源码 UWB全套源码
    现代制造业厂区面积大、人员数量多、物资设备不断增加,随着工业信息化技术的发展,大型制造企业中对人员、车辆、物资的管理要求越来越细致。高精度定位管理系统使用UWB室内定位技术,通过在厂区安装定位基站,为人员或设备佩戴定位标签的形式,实现人员精准实时定位。可以实现人员、车辆物......
  • 登录拦截器校验JWT
    importcom.alibaba.csp.sentinel.util.StringUtil;importcom.xtw.enums.BizCodeEnum;importcom.xtw.model.LoginUser;importcom.xtw.util.CommonUtil;importcom.xtw.util.JWTUtil;importcom.xtw.util.JsonData;importio.jsonwebtoken.Claims;importorg.springf......
  • h5养鸡游戏看广告源码开发
      H5养鸡游戏模式有app和小程序模式,都是以看广告模式出现,但是H5形式也可以开发,但怎么运营就看客户怎么操作了。其实网页版的游戏无非就是充值,商城卖货,返利等模式。  首先,我们需要设计游戏的功能和界面。在游戏设计中,我们需要考虑小鸡的生长周期、饲料消耗、疾病预防等问题......
  • 广告变现游戏试玩软件源码搭建
      广告变现游戏软件涉及到的游戏多,想要搭建一个这样的软件其实并不是难,难的是软件开发和后期的运营。看广告的游戏软件其实就是一个游戏加了一个广告,但是这里面的软件开发技术和变现的方式都有哪些呢。  开发对应的游戏就选择相应的游戏引擎,例如Unity或者是laiya开发。选......
  • 小游戏看广告复活软件app源码
      国内的移动手机用户居多,这促进了娱乐行业小游戏的发展,小游戏是人们日常消磨时间的工具。在玩游戏中消除乏味的生活,玩游戏时也会出现角色的失败,开发商也有应对游戏结束的方法,那就是花钱复活或者看广告复活。为了解决这个问题看广告复活的游戏就出现了,这款软件也就带来了很大的......