zoukankan      html  css  js  c++  java
  • rest framework-认证&权限&限制-长期维护

    ###############   自定义token认证    ###############

    class User(models.Model):
        name=models.CharField(max_length=32)
        pwd=models.CharField(max_length=32)
        type_choices=((1,"普通"),(2,"VIP"),(3,"SVIP"))
        user_type=models.IntegerField(choices=type_choices,default=1)
    
    
    class Token(models.Model):
        user=models.OneToOneField("User")
        token=models.CharField(max_length=128)
        def __str__(self):
            return self.token

    视图

    def get_random_str(user):
        import hashlib,time
        ctime=str(time.time())
    
        md5=hashlib.md5(bytes(user,encoding="utf8")) # 加盐处理,时间和user进行组合生成md5,
        md5.update(bytes(ctime,encoding="utf8"))
    
        return md5.hexdigest()
    
    
    class LoginModelView(APIView):
        authentication_classes = []
        permission_classes = []
        def post(self,request):
            name = request.data.get("name")
            pwd=request.data.get("pwd")
    
            user=User.objects.filter(name=name,pwd=pwd).first()
            res={"state_code":100,"msg":None}
            if user:
                # 登陆成功,
                random_str=get_random_str(user.name)
                token=Token.objects.update_or_create(user=user,defaults={"token":random_str})
                res["token"]=str(token)
            else:
                res["state_code"]=1001  #错误状态码
                res["msg"] = "用户名或者密码错误"
    
            import json
            return Response(json.dumps(res))

    认证类

    from rest_framework import exceptions
    from rest_framework.authentication import BaseAuthentication
    from .models import *
    
    class TokenAuth(BaseAuthentication):
        def authenticate(self,request):
            token=request.GET.get("token")
            token_obj=Token.objects.filter(token=token).first()
            if not token_obj:
                raise exceptions.AuthenticationFailed("验证失败!")
            else:
                return token_obj.user.name,token_obj.token

    视图级别认证

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

    全局级别认证

    # 在settings.py中配置
    REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
    }

    ###############   权限    ###############

    自定义一个权限类

    # 自定义权限
    class MyPermission(BasePermission):
        message = 'VIP用户才能访问'
    
        def has_permission(self, request, view):
            """
            自定义权限只有VIP用户才能访问
            """
            # 因为在进行权限判断之前已经做了认证判断,所以这里可以直接拿到request.user
            if request.user and request.user.type == 2:  # 如果是VIP用户
                return True
            else:
                return False

    第二种:

    class SVIPPermission(object):
        message="只有超级用户可以访问"
        def has_permission(self,request,view):
            username=request.user
            user_type=User.objects.filter(name=username).first().user_type
            if user_type==3:
                return True
            else:
                return False

    视图级别权限

    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_CLASSES": ["app01.utils.MyAuth", ],
        "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
    }

    ###############  限制    ###############

    自定义限制类

    VISIT_RECORD = {}
    # 自定义限制
    class MyThrottle(object):
    
        def __init__(self):
            self.history = None
    
        def allow_request(self, request, view):
            """
            自定义频率限制60秒内只能访问三次
         这是一个小需求,每个人理解不一样,思路即使把每次访问的ip保存下来,
         怎么获取iP是通过请求头,
         1,把每次访问的时间戳保持起来,{127.0.0.1:{13213,123123,12313}},
         2,每次插入时间戳都往第一个位置插入,然后把1分钟以外的时间戳都去掉,然后判是否>3个,如果是就不能访问,否则就允许访问,
    """ # 获取用户IP ip = request.META.get("REMOTE_ADDR") timestamp = time.time() if ip not in VISIT_RECORD: VISIT_RECORD[ip] = [timestamp, ] return True history = VISIT_RECORD[ip] self.history = history history.insert(0, timestamp) while history and history[-1] < timestamp - 60: history.pop() if len(history) > 3: return False else: return True def wait(self): """ 限制时间还剩多少 """ timestamp = time.time() return 60 - (timestamp - self.history[-1])

    视图级别限制

    class CommentViewSet(ModelViewSet):
    
        queryset = models.Comment.objects.all()
        serializer_class = app01_serializers.CommentSerializer
        throttle_classes = [MyThrottle, ]

    全局级别限制

    # 在settings.py中设置rest framework相关配置项
    REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
        "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
        "DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]
    }

    ###############   结束线    ###############

  • 相关阅读:
    测试
    Python 学习笔记【15】文件操作
    Python 学习笔记【14】集合
    Python 学习笔记【13】练习:三级菜单
    Python 学习笔记【12】字典
    Python 学习笔记【11】字符串操作
    Python 学习笔记【10】练习:购物车程序
    Python 学习笔记【09】列表、元组
    Python 学习笔记【08】数据类型、数据运算、进制转换
    Python 学习笔记【07】PEP 8 中英对照
  • 原文地址:https://www.cnblogs.com/andy0816/p/12293728.html
Copyright © 2011-2022 走看看