zoukankan      html  css  js  c++  java
  • DRF三大认证

    认证组件authentication

    一般使用全局配置

    settings中配置
    REST_FRAMEWORK = {
        # 认证组件
        'DEFAULT_AUTHENTICATION_CLASSES': [
            #系统自带两个认证类
            # 'rest_framework.authentication.SessionAuthentication',
            # 'rest_framework.authentication.BasicAuthentication'
            'rest_framework_jwt.authentication.JSONWebTokenAuthentication'
        ],
    }
    
    自定义权限类
    1. 如果使用session认证,drf提供了SessionAuthentication类认证
    2. 如果使用drf-jwt认证框架,drf-jwt提供了JSONWebTokenAuthentication类认证
    3. 如果自定义签发与校验token,需要将校验token的算法封装到自定义的认证类中.
      1. 从请求头中获取前台提交的token(一般从HTTP_AUTHORIZATION中拿,也可以与前台交流好),这是为了设置反爬措施,校验反爬.
      2. 没有token,返回None,代表游客.
      3. 由token,进入校验.
        1. 不通过,抛出AuthenticationFailed异常,代表非法用户
        2. 通过,返回(user,token)二元组,代表合法用户
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    from rest_framework_jwt.authentication import JSONWebTokenAuthentication
    class MyAuthentication(BaseAuthentication):
        def authenticate(self, request):
            pass
    

    总结:

    不带或者认证格式错误,相当于游客访问,

    带了正确的请求格式,但是token信息错误,为非法用户,并抛出AuthenticationFailed异常

    权限组件permission

    一般使用局部配置,导入模块,在视图函数中配置组件

    permission_classes = [IsAuthenticated]
    
    系统自带权限类

    AllowAny:游客和登录用户有全权限

    IsAuthenticated:只有登录用户有全权限

    IsAdminUser:只有后台用户(admin用户)有全权限

    IsAuthenticatedOrReadOnly:游客有读权限,登录用户有全权限

    也可以全局配置
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ],
    
    自定义权限类

    如有特殊需求,比如:只有superuser有权限、只有vip用户有权限、只有某ip网段用户有权限、只有某个视图及其子类有权限.

    has_permission方法的返回值为bool型,True为拥有权限,反之False无权限.

    class MyPermission(BasePermission):
        def has_permission(self, request, view):
            """
            1) 根据需求,request和view的辅助,制定权限规则判断条件
            2)如果条件通过,返回True
            3)如果条件不通过,返回False
            """
            print(request.user, request.auth)
            return True
    

    vip用户权限

    class VIPUserPermission(BasePermission):
        def has_permission(self, request, view):
            for group in request.user.groups.all():
                if group.name.lower() == 'vip':
                    return True  #有权限
            return False #无权限
    

    频率组件throttle

    settings中配置,

    REST_FRAMEWORK = {
        # 频率组件:频率类一般做局部配置,但是频率调节在settings中配置
        'DEFAULT_THROTTLE_RATES': {
            'user': '5/min',
            'anon': '3/min',
            'mobile': '1/min'
        },
    }
    
    默认配置

    不配置默认无频率认证

    drf默认提供了一些频率类

    AnonRateThrottle:只对游客进行频率限制

    UserRateThrottle:对所有用户进行频率限制

    自定义配置

    如果有特殊需求,需要自定义频率类

    如:对IP进行限次,对电话进行限制,对视图某些信息进行限次

    class MobileRateThrottle(SimpleRateThrottle):
        """
        1)设置scope字符串类属性,同时在settings中进行drf配置DEFAULT_THROTTLE_RATES
            eg: DEFAULT_THROTTLE_RATES = {'mobile': '1/min'}
        2)重写get_catch_key方法:
            返回与限制条件有关的字符串,表示限制
            返回None,表示不限制
        """
        scope = 'mobile'
        def get_cache_key(self, request, view):
            if not request.user.is_authenticated or not request.user.mobile:
                return None  # 匿名用户 或 没有电话号的用户 都不限制
    
            # 只要有电话号的用户踩进行限制
            return self.cache_format % {
                'scope': self.scope,
                'ident': request.user.mobile
            }
    

    多方式登录

    1. token只能由 登录接口 签发
    2. 登录接口也是APIView的子类,使用一定会进行 认证,权限 组件的校验

    结论:不管系统默认,或是全局settings配置的何种认证与权限组件,登录接口不用参与任何认证与权限的校验

    所以,登录接口一定要进行 认证与权限的局部禁用

    方法

    登录接口中设置局部禁用

    class LoginAPIView(APIView):
        #认证与权限接口的局部禁用
        authentication_classes = []
        permission_classes = []
    
        def post(self, request, *args, **kwargs):
            serializer = serializers.LoginModelSerializer(data=request.data)
            serializer.is_valid(raise_exception=True)  # 内部在全局钩子中完成token的签发
            return APIResponse(results={
                'username': serializer.content.get('user').username,
                'token': serializer.content.get('token')
            })
    

    多方式登录的验证规则刚在serializers中,通过全局钩子进行校验

    from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
    import re
    class LoginModelSerializer(serializers.ModelSerializer):
        # post请求,序列化默认当做create动作进行校验,需要校验数据库,create动作username会抛用户已存在异常
        # 抛用户已存在异常是多余的,所以自定义系统校验规则即可
        username = serializers.CharField(min_length=3, max_length=16)
        password = serializers.CharField(min_length=3, max_length=16)
        class Meta:
            model = models.User
            fields = ('username', 'password')
    
        # 用全局钩子,完成token的签发
        def validate(self, attrs):
            # 1)通过 username 和 password 完成多方式登录校验,得到user对象
            user = self._validate_user(attrs)
            # 2)user对象包装payload载荷
            payload = jwt_payload_handler(user)
            # 3)payload载荷签发token
            token = jwt_encode_handler(payload)
            # 4)将user与token存储到serializer对象中,方便在视图类中使用
            self.content = {
                'user': user,
                'token': token
            }
            return attrs
    
        def _validate_user(self, attrs):
            username = attrs.get('username')
            password = attrs.get('password')
    
            if re.match(r'.*@.*', username):  # 邮箱
                user = models.User.objects.filter(email=username).first()  # type: models.User
            elif re.match(r'^1[3-9][0-9]{9}$', username):  # 电话
                user = models.User.objects.filter(mobile=username).first()
            else:  # 用户名
                user = models.User.objects.filter(username=username).first()
    
            if not user or not user.check_password(password):
                raise serializers.ValidationError({'message': '用户信息异常'})
    
            return user
    
  • 相关阅读:
    static 续--
    [非原创]java 中static作用解析
    public/private/protected作用域
    三种排序方法(冒泡、选择、插入)
    SQLMAP自动注入(四)
    SQLMAP自动注入(三)—Injection,Detection,Techniques
    SQLMAP自动注入(二)-request,优化
    SQLMAP自动注入(一)
    SQL盲注
    SQL注入——猜测字段名称
  • 原文地址:https://www.cnblogs.com/1012zlb/p/12146348.html
Copyright © 2011-2022 走看看