• drf8


    昨日回顾

    1 分页功能
    	-三个类:普通分页,偏移分页,游标分页
        -每个类中都有几个属性:查询的字段,每页显示的条数,每页最多显示的条数,游标分页中有个排序
        -定义一个类,继承上面3个其中一个,重写字段
        -继承了APIView:实例化得到分页对象,把要分页的数据传入,返回分页后的数据,序列化,可以按照自己定制的规则返回,也可也使用page.get_paginated_response(ser.data)
        -如果继承了ListModelMixin和GenericAPIView,直接配置就可以了
        	pagination_class = MyCursorPagination
    2 全局异常
    	-写一个方法
        def common_exception_handler(exc, context):
            response = exception_handler(exc, context)
            if response is None:
                response = Response({'code': 999, 'detail': str(exc)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            return response
       	-setting中配置一下
        	'EXCEPTION_HANDLER':'app01.utils.common_exception_handler'
        -通常情况咱们会记录日志
        	-使用django日志记录  xx.log文件中
            -使用sentry(公司自己写)日志记录, 平台(django),查询,统计,告警
    3 自己写的Response
    	class APIResponse(Response):
            def __init__(self, code=100, msg='成功', data=None, status=None, headers=None, content_type=None, **kwargs):
                dic = {'code': code, 'msg': msg}
                if data:
                    dic['data'] = data
                dic.update(kwargs) # 这里使用update
                super().__init__(data=dic, status=status,
                                 template_name=None, headers=headers,
                                 exception=False, content_type=content_type)
        #我们期望这种格式
        {
            code:100
            msg:成功,失败信息
            data:[]
            count:
        }
        # 使用
        APIResponse(data=[],code=101,heades={})
        
    4 自动生成接口文档
    	-手写
        -自动生成(drf:crorapi),swagger(java,go,python)
        	-安装:pip3 install coreapi
            -路由中配置:path('docs/', include_docs_urls(title='图书管理系统api')),
            -在配置文件中配置:'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
            -写视图类,在里面要加注释,就在接口平台就能看到
            
    # 重写get_serializer_class,实现不同的请求,返回的序列化类不一样,(在同一视图函数中,不同的序列化类中)
    class UserView(GenericViewSet, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin):
        queryset = UserInfo.objects.all()  # 类似的get_queryset重写,返回什么就是什么要序列化的对象
        serializer_class = UserModelSerializer
        
        def get_serializer_class(self):
            # 可以根据请求方式
            if self.action == 'create':
                return UserModelSerializer   # 返回那个序列化,就用的哪个序列化
            elif self.action == 'retrieve':
                return UserReadOnlyModelSerializer
            elif self.action == 'update':
                return UserIconModelSerializer
    

    今日内容

    4 jwt认证介绍

    1 不再使用Session认证机制,而使用Json Web Token(本质就是token)认证机制,用户登录认证
    2 用户只要登录了,返回用户一个token串(随机字符串),每次用户发请求,需要携带这个串过来,验证通过,我们认为用户登录了
    3 JWT的构成(字符串)
    	-三部分(每一部分中间通过.分割):header   payload  signature
        -header:明类型,这里是jwt,声明加密算法,头里加入公司信息...,base64转码
            {
              'typ': 'JWT',
              'alg': 'HS256'
            }
        -payload:荷载(有用),当前用户的信息(用户名,id,这个token的过期时间,手机号),base64转码
            {
              "sub": "1234567898",
              "name": "egon",
              "admin": true,
              "userid":1,
              'mobile':123444444
            }
        -signature:签名
        	-把前面两部分的内容通过加密算法+密钥加密后得到的一个字符串
        -jwt总的构成样子:
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
            
    4 JWT认证原理
    	-用户携带用户名,密码登录我的系统,校验通过,生成一个token(三部分),返回给用户---》登录功能完成
        -访问需要登录的接口(用户中心),必须携带token过来,后端拿到token后,把header和payload截出来,再通过一样的加密方式和密码得到一个signature,和该token的signature比较,如果一样,表示是正常的token,就可以继续往后访问
    

    5 base64介绍和使用

    1 任何语言都有base64的加码和解码,转码方式(加密方式)
    2 python中base64的加密与解密
        import base64
        import json
        dic_info={
          "name": "lqz",
          "age": 18
        }
        # 转成json格式字符串
        dic_str=json.dumps(dic_info)
        print(dic_str)
        # 加密 需要用bytes格式
        base64_str=base64.b64encode(dic_str.encode('utf-8'))
        print(base64_str)
        # 解密 需要用bytes格式
        res_bytes=base64.b64decode('eyJuYW1lIjogImxxeiIsICJhZ2UiOiAxOH0=')
        print(res_bytes)
    

    6 jwt基本使用(jwt内置,控制用户登录后能访问和未登陆能访问)

    1 drf中使用jwt,借助第三方https://github.com/jpadilla/django-rest-framework-jwt
    2 pip3 install djangorestframework-jwt
    3 快速使用(默认使用auth的user表)
    	1 再默认auth的user表中创建一个用户
        2 在路由中配置导入from rest_framework_jwt.views import obtain_jwt_token
        	path('login/', obtain_jwt_token),
        3 用postman向这个地址发送post请求,携带用户名,密码,登陆成功就会返回token
        4 obtain_jwt_token本质也是一个视图类,继承了APIView
        	-通过前端传入的用户名密码,校验用户,如果校验通过,生成token,返回
            -如果校验失败,返回错误信息 
    4 用户登录以后才能访问某个接口
    	-jwt模块内置了认证类,拿过来局部配置就可以
        from rest_framework_jwt.authentication import JSONWebTokenAuthentication
        from rest_framework.permisssions import IsAuthenticated
        -class OrderView(APIView):
            # 只配它不行,不管是否登录,都能访问,需要搭配一个内置权限类,并且token需要放在请求头中
            authentication_classes = [JSONWebTokenAuthentication, ]
            permission_classes = [IsAuthenticated,]
            def get(self, request):
                print(request.user.username)  # 带了之后能够打印出个人的信息
                return Response('订单的数据')
    
    5 用户未登录,不能访问
        -class OrderView(APIView):
            # 只配它不行,不管是否登录,都能访问,需要搭配一个内置权限类
            authentication_classes = [JSONWebTokenAuthentication, ]
            def get(self, request):
                print(request.user.username)
                return Response('订单的数据')
            
    6 如果用户携带了token,并且配置了JSONWebTokenAuthentication,从request.user就能拿到当前登录用户,如果没有携带,当前登录用户就是匿名用户
    7 前端要发送请求,携带jwt,格式必须如下
    	-把token放到请求头中,key为:Authorization 
        -value必须为:jwt eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo1LCJ1c2VybmFtZSI6ImVnb24xIiwiZXhwIjoxNjA1MjQxMDQzLCJlbWFpbCI6IiJ9.7Y3PQM0imuSBc8CUe_h-Oj-2stdyzXb_U-TEw-F82WE
    

    7 控制登录接口返回的数据格式

    源码中默认的只返回了token,但告知可以序列化之后再返回序列化后的数据
    1 控制登录接口返回的数据格式如下
        {
        code:100
        msg:登录成功
        token:asdfasfd
        username:egon
        }
    2 在app下新建一个py文件写一个函数
    	from homework.serializer import UserReadOnlyModelSerializer
        def jwt_response_payload_handler(token, user=None, request=None):  # 函数名无所谓,参数必须传这么几个
            return {'code': 100, 
                    'msg': '登录成功',
                    'token': token,
                    'user': UserReadOnlyModelSerializer(instance=user).data  # 自写的序列化类.data转成了字典
                    }   # 自定制的返回格式
    3 在setting.py中配置,是函数文件生效
    	import datetime
        JWT_AUTH = {
            'JWT_EXPIRATION_DELTA': datetime.timedelta(days=2),  # 设置过期时间,不设置,源码中默认300s
            'JWT_RESPONSE_PAYLOAD_HANDLER': 'homework.utils.jwt_response_payload_handler',  # 函数所在的路径
        }
    

    8 自定义基于jwt的认证类

    1 因为模块中自带的需要认证类配合使用,因此可以自己实现基于jwt的认证类,通过认证,才能继续访问,通不过认证就返回错误,可以将 #key值可以随意叫,token信息可以放在请求头中,请求地址中,也不用带jwt空格然后token,
    2 代码如下导入 from rest_framework_jwt.utils import jwt_decode_handler
    import jwt,from rest_framework_jwt.authentication import JSONWebTokenAuthentication,from rest_framework exceptions import AuthenticationFailed
        class JwtAuthentication(BaseJSONWebTokenAuthentication): # 即写一个类,继承BaseJSONWebTokenAuthentication,重写里面认证的方法authenticate
            def authenticate(self, request):
                # 认证逻辑()
                # token信息可以放在请求头中,请求地址中,再认证的代码中,从哪取token决定了前端将数据放在哪个地方,否则取不出token值
                # key值可以随意叫
                # token=request.GET.get('token')
                token=request.META.get('HTTP_Authorization'.upper())
                # 校验token是否合法
                try:
                    payload = jwt_decode_handler(token)
                except jwt.ExpiredSignature:
                    raise AuthenticationFailed('过期了')
                except jwt.DecodeError:
                    raise AuthenticationFailed('解码错误')
                except jwt.InvalidTokenError:
                    raise AuthenticationFailed('不合法的token')
                user=self.authenticate_credentials(payload)
                return (user, token)
     3 在视图类中配置
    	authentication_classes = [JwtAuthentication, ]
    
  • 相关阅读:
    mysql 查询本年当前季度数据
    eclipse导入项目出现红叉怎么办
    input框只能输入正数
    解压MAC压缩的zip文件
    文件上传,文件下载,解压zip文件,判断压缩文件里面包含几个文件,判断压缩文件里是否包含指定的后缀文件
    解决IE下readonly的Input光标选中的问题
    前端JS下载文件总结
    Angular变更检测策略报错
    笛卡尔算法
    Angualr 内置工具-SelectionModel
  • 原文地址:https://www.cnblogs.com/feiguoguobokeyuan/p/14044117.html
Copyright © 2020-2023  润新知