zoukankan      html  css  js  c++  java
  • DRF 认证、权限、限制

    认证:

      定义一个用户表和一个保存用户的Token表

    # ======================day96=======================
    
    class UserInfo(models.Model):
        username = models.CharField(max_length=16,unique=True)
        password = models.CharField(max_length=32)
    
        type = models.SmallIntegerField(
            choices=((1,"普通用户"),(2,"VIP用户")),
            default=1
        )
    
    class Token(models.Model):
        token = models.CharField(max_length=128)
        user = models.OneToOneField(to="UserInfo",on_delete=models.CASCADE)

      定义一个登陆视图:

    # 生成Token的函数
    def get_token_code(username):
        """
        根据用户名和时间戳来生成永不相同的token随机字符串
        :param username: 字符串格式的用户名
        :return: 字符串格式的Token
        """
    
        import time
        import hashlib
    
        timestamp = str(time.time())
        m = hashlib.md5(username.encode("utf-8"))
        # md5 要传入字节类型的数据
        m.update(timestamp.encode("utf-8"))
        return m.hexdigest()  # 将生成的随机字符串返回
    
    # 登陆视图
    
    class LoginView(APIView):
        '''
        登陆检测试图。
        1,接收用户发过来的用户名和密码数据
        2,校验用户密码是否正确
            - 成功就返回登陆成功,然后发Token
            - 失败就返回错误提示
        '''
    
        def post(self,request):
            res = {"code":0}
            # 从post 里面取数据
            print(request.data)
            username = request.data.get("username")
            password = request.data.get("password")
            # 去数据库查询
            user_obj = models.UserInfo.objects.filter(
                username = username,
                password = password
            ).first()
            if user_obj:
                # 登陆成功
                # 生成Token
                token = get_token_code(username)
                # 将token保存
                # 用user = user_obj 这个条件去Token表里查询。
                # 如果又记录就更新default里传的参数,没有记录就用default里传的参数创建一条数据。
                models.Token.objects.update_or_create(defaults={"token":token},user = user_obj)
                # 将token返回给用户
                res["token"] = token
            else:
                # 登陆失败
                res["code"] = 1
                res["error"] = "用户名或密码错误"
            return Response(res)

    新建一个utils文件夹 下面放一些组件:

      定义一个MyAuth认证类:

    """
    这里放自定义的认证类
    """
    from rest_framework.authentication import BaseAuthentication
    from app01 import models
    from rest_framework.exceptions import AuthenticationFailed
    
    
    class MyAuth(BaseAuthentication):
    
        def authenticate(self, request):
            # print(request.method)
            if request.method in ["POST","PUT","DELETE"]:
                # 如果请求是post,put,delete三种类型时
                # 获取随用户请求发来的token随机码
                token = request.data.get("token")
                # 然后去数据库查询有没有这个token
                token_obj = models.Token.objects.filter(token=token).first()
                if token_obj:
                    # 如果存在,则说明验证通过,以元组形式返回用户对象和token
                    return token_obj.user,token
                else:
                    # 不存在就直接抛错
                    raise AuthenticationFailed("无效的token")
            else:
            # 这一步的else 是为了当用户是get请求时也可获取数据,并不需要验证token.
                return None,None

    视图级别认证:

    class CommentViewSet(ModelViewSet):
        queryset = models.Comment.objects.all()
        serializer_class = app01_serializers.CommentSerializer
        authentication_classes = [MyAuth,]
        permission_classes = [MyPermission,]

    全局级别认证:需要在settings.py文件设置:

    # REST FRAMEWORK 相关的配置
    
    REST_FRAMEWORK = {
        # 关于认证的全局配置
        # "DEFAULT_AUTHENTICATION_CALSSES": ["app01.utils.auth.MyAuth",],
        # "DEFAULT_PERMISSION_CLASSES" : ["app01.utils.permission.MyPermission"],
        # "DEFAULT_THROTTLE_CLASSES" : ["app01.utils.throttle.MyThrottle",],
        "DEFAULT_THROTTLE_CLASSES" : ["app01.utils.throttle.VisitThrottle",],
        "DEFAULT_THROTTLE_RATES":{
            "XXX":"5/m",
        }
    }

    权限:

      只有VIP用户才能看的内容:

      自定义权限类:

    '''
    自定义的权限类
    '''
    
    from rest_framework.permissions import BasePermission
    
    class MyPermission(BasePermission):
        message = "sorry,您没有权限"
        def has_permission(self, request, view):
            # 内置封装的方法
            '''
            判断该用户有没有权限
            '''
            # 判断用户是不是VIP用户
            # 如果是VIP用户就返回True
            # 如果是普通用户就返会Flase
    
            if request.method in ["POST","PUT","DELETE"]:
                # print(111)
                print(request.user.username)
                print(request.user.type)
                print(type(request.user.type))
                if request.user.type == 2:   # 是VIP用户
                    print(2222)
                    return True
                else:
                    return False
            else:
                return True
    
        def has_object_permission(self, request, view, obj):
            # 用来判断针对的obj权限:
            # 例如:是不是某一个人的评论
            '''
            只有评论人是自己才能删除选定的评论
            '''
            if request.method in ["PUT","DELETE"]:
                print(obj.user.username)
                print(request.user.username)
                if obj.user == request.user:
                    # 表示当前评论对象的用户就是登陆用户
                    return True
                else:
                    return False
            else:
                return True

    视图级别配置:

    class CommentViewSet(ModelViewSet):
        queryset = models.Comment.objects.all()
        serializer_class = app01_serializers.CommentSerializer
        authentication_classes = [MyAuth,]
        permission_classes = [MyPermission,]

    全局级别配置:

    # REST FRAMEWORK 相关的配置
    
    REST_FRAMEWORK = {
        # 关于认证的全局配置
        # "DEFAULT_AUTHENTICATION_CALSSES": ["app01.utils.auth.MyAuth",],
        # "DEFAULT_PERMISSION_CLASSES" : ["app01.utils.permission.MyPermission"],
        # "DEFAULT_THROTTLE_CLASSES" : ["app01.utils.throttle.MyThrottle",],
        "DEFAULT_THROTTLE_CLASSES" : ["app01.utils.throttle.VisitThrottle",],
        "DEFAULT_THROTTLE_RATES":{
            "XXX":"5/m",
        }
    }

    限制:

      自定义限制类:

    '''
    自定义的访问限制类
    '''
    
    from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
    import time
    
    # =============================
    # DIC = {}
    #
    # class MyThrottle(BaseThrottle):
    #     def allow_request(self, request, view):
    #         '''
    #         返回True就放行,返回False表示被限制了
    #         '''
    #
    #         # 获取当前访问的ip地址
    #         ip = request.META.get("REMOTE_ADDR")
    #
    #         # 获取当前时间
    #         now = time.time()
    #
    #         # 判断当前ip是否有访问记录
    #         if ip not in DIC:
    #             DIC[ip] = []    # 如果没有访问记录初始化一个空的访问历史列表
    #
    #         # 高端操作
    #         history = DIC[ip]
    #         # 当当前ip存在访问记录,且现在的访问时间比最初的一次访问时间大于10秒
    #         while history and now - history[-1] > 10:
    #             history.pop()   # 删掉历史列表中的最后一个记录
    #         # 判断最近一分钟的访问次数是否超过了阈值(3次)
    #         if len(history)>=3:
    #             return False
    #         else:
    #             # 把这一次的访问时间加到访问历史列表的第一位
    #             DIC[ip].insert(0,now)
    #             return True
    
    
    # ==============================
    # 以上代码等同于一下代码
    class VisitThrottle(SimpleRateThrottle):
        scope = 'XXX'
    
        def get_cache_key(self, request, view):
            return self.get_ident(request)   # 求当前访问的IP

    视图级别:

    from app01.utils.auth import MyAuth
    from app01.utils.permission import MyPermission
    from app01.utils.throttle import SimpleRateThrottle
    # from app01.utils.throttle import
    class CommentViewSet(ModelViewSet):
        queryset = models.Comment.objects.all()
        serializer_class = app01_serializers.CommentSerializer
        authentication_classes = [MyAuth,]
        permission_classes = [MyPermission,]

    全局级别:

    # REST FRAMEWORK 相关的配置
    
    REST_FRAMEWORK = {
        # 关于认证的全局配置
        # "DEFAULT_AUTHENTICATION_CALSSES": ["app01.utils.auth.MyAuth",],
        # "DEFAULT_PERMISSION_CLASSES" : ["app01.utils.permission.MyPermission"],
        # "DEFAULT_THROTTLE_CLASSES" : ["app01.utils.throttle.MyThrottle",],
        "DEFAULT_THROTTLE_CLASSES" : ["app01.utils.throttle.VisitThrottle",],
        "DEFAULT_THROTTLE_RATES":{
            "XXX":"5/m",
        }
    }
  • 相关阅读:
    23种设计模式
    <转>企业应用架构 --- 分层
    <转>C/S架构分析
    Decorator 模式转载
    2019-10-24 体检结果备查,降甘油三脂药物
    Entity Framework Core 文档 & Core Web API 文档
    MSSQLLocalDB 微软本地数据库,pk SQLlite
    InstallWatch Pro
    学习 skoruba/ IdentityServer4.Admin 完整版
    无代码与低代码开发平台,云+本地,阿里/腾讯
  • 原文地址:https://www.cnblogs.com/stfei/p/9416652.html
Copyright © 2011-2022 走看看