<i id="d2xhp"></i>

      <font id="d2xhp"></font>
      <optgroup id="d2xhp"><del id="d2xhp"></del></optgroup>
        
        

            <i id="d2xhp"></i>

              <i id="d2xhp"><option id="d2xhp"></option></i>
              <i id="d2xhp"></i>
              <thead id="d2xhp"></thead>
              <object id="d2xhp"><option id="d2xhp"></option></object>

                JWT自定义校验规则与生成、用户多种方式登陆、搜索过滤,排序,分页


                # 自定义校验token规则
                1.视图类
                from .authentications import JWTAuthentication
                
                class UserDetail1(APIView):
                    permission_classes = [IsAuthenticated]  # 必须登录
                    authentication_classes = [JWTAuthentication]  # jwt用户token自定义登陆认证规则
                
                    def get(self, request, *args, **kwargs):
                        return APIResponse(results={username: request.user.username})
                2.自定义token规则,在api生成一个authentications.py认证文件
                import jwt
                from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
                from rest_framework_jwt.authentication import jwt_decode_handler
                from rest_framework.exceptions import AuthenticationFailed
                
                class JWTAuthentication(BaseJSONWebTokenAuthentication):
                    def authenticate(self, request):
                        jwt_token = request.META.get(HTTP_AUTHORIZATION)
                
                        # 自定义规则 :auth token jwt,调用下面规则方法
                        token = self.parse_jwt_token(jwt_token)
                
                        # 如果没有值,无法校验
                        if token is None:
                            return None
                
                        try:
                            # token =>payload  反向解析出payload
                            payload = jwt_decode_handler(token)
                        except jwt.ExpiredSignature:  # 判断是否过期
                            raise AuthenticationFailed(token已过期)
                        except:
                            raise AuthenticationFailed(非法用户)
                        user = self.authenticate_credentials(payload) # 根据payload解析出user
                
                        return (user, token)
                
                    # 自定义校验规则:auth token jwt ,auth为前言,jwt为后缀
                    def parse_jwt_token(self, jw_token):
                        tokens = jw_token.split()
                        if len(tokens) != 3 or tokens[0].lower() != auth or tokens[2].lower() != jwt:
                            return None
                        # 把token核心内容返回进行校验
                        return tokens[1]

                # 自定义 drf-jwt 配置
                import datetime
                JWT_AUTH = {
                    # user => payload
                    JWT_PAYLOAD_HANDLER:
                        rest_framework_jwt.utils.jwt_payload_handler,
                    # payload => token
                    JWT_ENCODE_HANDLER:
                        rest_framework_jwt.utils.jwt_encode_handler,
                    # token => payload
                    JWT_DECODE_HANDLER:
                        rest_framework_jwt.utils.jwt_decode_handler,
                    # token过期时间
                    JWT_EXPIRATION_DELTA: datetime.timedelta(days=7),
                    # token刷新的过期时间
                    JWT_REFRESH_EXPIRATION_DELTA: datetime.timedelta(days=7),
                    # 反爬小措施前缀
                    JWT_AUTH_HEADER_PREFIX: JWT,
                }

                实现多种方式登录签发token:比如 -账号、手机号、邮箱等登录:
                1.禁用认证与权限组件
                2.拿到前台登录信息,交给序列化类
                3.序列化校验得到登陆用户与token存放在序列化对象中
                4.取出登陆用户与token返回给前台
                """

                from .serializers import UserModelSerializer

                # 1.视图类
                class LoginAPIView(APIView):
                    authentication_classes = []  # 禁用认证
                    permission_classes = []  # 禁用权限
                
                    def post(self, request, *args, **kwargs):
                        user_ser = UserModelSerializer(data=request.data)  # 反序列化进行校验
                        # 校验通过,如果没有报异常
                        user_ser.is_valid(raise_exception=True)
                
                        # 正常登陆,把生成的token返回给前端
                        return APIResponse(token=user_ser.token, results=UserModelSerializer(user_ser.user).data)
                  
                #2. 序列化类,进行校验,生成token发送出去
                from rest_framework import serializers
                from . import models
                import re
                
                from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
                
                class UserModelSerializer(serializers.ModelSerializer):
                    # 自定义反序列化字段:一定要设置write_only,值参与反序列化,不会与model类字段映射
                    usr = serializers.CharField(write_only=True)
                    pwd = serializers.CharField(write_only=True)
                
                    class Meta:
                        model = models.User
                        fields = [usr, pwd, username, mobile, email]
                        # 系统校验规则
                        extra_kwargs = {
                            # ‘usr‘: {
                                # ‘required‘: True,  # 必须校验
                            #     ‘min_length‘: 3,
                            #     ‘error_messages‘: {
                            #         ‘required‘: ‘必须填写,你个铺盖‘,
                            #         ‘min_length‘: ‘太短楼!‘,
                            #     }
                            # },
                            username: {
                                read_only: True
                            },
                            mobile: {
                                read_only: True
                            },
                            email: {
                                read_only: True
                            }
                
                        }
                
                    # 全局钩子,attrs里面是通过校验的
                    def validate(self, attrs):
                        usr = attrs.get(usr)
                        pwd = attrs.get(pwd)
                        # 多方式登录:各分支处理得到该方式对应的用户
                        if re.match(r[email protected]+, usr):
                            user_query = models.User.objects.filter(email=usr)
                        elif re.match(r1[3-9][0-9]{9}, usr):
                            user_query = models.User.objects.filter(mobile=usr)
                        else:
                            user_query = models.User.objects.filter(username=usr)
                        user_obj = user_query.first()
                
                        if user_obj and user_obj.check_password(pwd):
                            # 签发生成token,将token存放到实例化对象的中
                            payload = jwt_payload_handler(user_obj)  # 把头部,和载荷过期时间,user对象,生成payload
                            token = jwt_encode_handler(payload)  # 把头部,载荷,和秘=秘钥经过加密生成token
                            self.token = token  # 把token赋值到对象中
                            self.user = user_obj
                            print(token)
                            return attrs
                        raise serializers.ValidationError({data: 数据提供有误})
                 
                搜索过滤,排序,分页:
                from . import models
                from .serializers import CarModelSerializer
                # Car的群查接口
                from rest_framework.generics import ListAPIView
                
                # 1.drf的SearchFilter - 搜索过滤
                from rest_framework.filters import SearchFilter
                
                # 2.drf的OrderingFilter - 排序过滤
                from rest_framework.filters import OrderingFilter
                
                # 3.drf的分页类 - 自定义
                from . import pagenations
                
                class CarListAPIView(ListAPIView):
                    permission_classes = []  # 权限取消
                    authentication_classes = []  # 认证取消
                
                    queryset = models.Car.objects.all()
                    serializer_class = CarModelSerializer
                
                    # 局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
                    filter_backends = [SearchFilter,OrderingFilter]
                
                    # SearchFilter过滤类依赖的过滤条件 => 接口:/cars/?search=...
                    search_fields = [name, price]
                
                    # OrderingFilter过滤类依赖的过滤条件 => 接口:/cars/?ordering=...,正是升序,-则是降序
                    ordering_fields = [pk, price]
                    # eg:/cars/?ordering=-price,pk,先按price降序,如果出现price相同,再按pk升序
                
                    pagination_class = pagenations.MyPageNumberPagination
                 
                # 自定义分页类
                from rest_framework.pagination import PageNumberPagination
                
                class MyPageNumberPagination(PageNumberPagination):
                    # ?page=页码
                    page_query_param = page
                
                    # ?page=页面 下默认一页显示的条数
                    page_size = 3
                
                    # ?page=页面&page_size=条数 用户自定义一页显示的条数
                    page_size_query_param = page_size
                
                    max_page_size = 5
                相关文章
                相关标签/搜索
                黄大仙心水高手免费资料