• 认证组件


    认证组件

    重点

    1 认证规则

    2 如何自定义认证类

    3 我们一般不需要自定义认证类,在 settings 中全局配置第三方 jwt 认证组件提供的认证类即可


    自定义认证类

    1 自定义认证类,继承 BaseAuthentication 类

    2 必须重写 authenticate(self, request) 方法

    没有认证信息,返回None:匿名用户(游客) => 匿名用户request.user也有值,就是"匿名对象(Anonymous)"

    有认证信息,且通过,返回(user, token):合法用户 => user对象会存到request.user中

    有认证信息,不通过,抛异常:非法用户



    认证组件项目使用:多方式登陆

    urls.py

    # 自定义登录(重点):post请求 => 查操作(签发token返回给前台) - 自定义路由映射
    url('^user/login/$', views.LoginViewSet.as_view({'post': 'login'})),
    

    views.py

    # 重点:自定义login,完成多方式登录
    from rest_framework.viewsets import ViewSet
    from rest_framework.response import Response
    class LoginViewSet(ViewSet):
        # 登录接口,要取消所有的认证与权限规则,也就是要做局部禁用操作(空配置)
        authentication_classes = []
        permission_classes = []
        
        # 需要和mixins结合使用,继承GenericViewSet,不需要则继承ViewSet
        # 为什么继承视图集,不去继承工具视图或视图基类,因为视图集可以自定义路由映射:
        #       可以做到get映射get,get映射list,还可以做到自定义(灵活)
        def login(self, request, *args, **kwargs):
            serializer = serializers.LoginSerializer(data=request.data, context={'request': request})
            serializer.is_valid(raise_exception=True)
            token = serializer.context.get('token')
            return Response({"token": token})
    

    serializers.py

    from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
    
    # 重点:自定义login,完成多方式登录
    class LoginSerializer(serializers.ModelSerializer):
        # 登录请求,走的是post方法,默认post方法完成的是create入库校验,所以唯一约束的字段,会进行数据库唯一校验,导致逻辑相悖
        # 需要覆盖系统字段,自定义校验规则,就可以避免完成多余的不必要校验,如唯一字段校验
        username = serializers.CharField()
        class Meta:
            model = models.User
            # 结合前台登录布局:采用账号密码登录,或手机密码登录,布局一致,所以不管账号还是手机号,都用username字段提交的
            fields = ('username', 'password')
    
        def validate(self, attrs):
            # 在全局钩子中,才能提供提供的所需数据,整体校验得到user
            # 再就可以调用签发token算法(drf-jwt框架提供的),将user信息转换为token
            # 将token存放到context属性中,传给外键视图类使用
            user = self._get_user(attrs)
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            self.context['token'] = token
            return attrs
    
        # 多方式登录
        def _get_user(self, attrs):
            username = attrs.get('username')
            password = attrs.get('password')
            import re
            if re.match(r'^1[3-9][0-9]{9}$', username):
                # 手机登录
                user = models.User.objects.filter(mobile=username, is_active=True).first()
            elif re.match(r'^.+@.+$', username):
                # 邮箱登录
                user = models.User.objects.filter(email=username, is_active=True).first()
            else:
                # 账号登录
                user = models.User.objects.filter(username=username, is_active=True).first()
            if user and user.check_password(password):
                return user
    
            raise ValidationError({'user': 'user error'})
    

  • 相关阅读:
    【LeetCode】1668.最大重复子字符串(三)
    【LeetCode】1929. 数组串联(4)——总结
    验证下MarkDown
    【LeetCode】27. 移除元素
    [Linux]cp command in Linux with examples
    【LeetCode】1929. 数组串联(2)
    【LeetCode】1668.最大重复子字符串(二)
    RAID6与RAID5区别
    【PyCharm/IntelliJ】How to solve "untrusted server's certificate"
    【JAVA】The difference between JDK and JRE
  • 原文地址:https://www.cnblogs.com/kai-/p/12363095.html
Copyright © 2020-2023  润新知