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", ]
}

 

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

 

posted @ 2020-02-11 07:18  技术改变命运Andy  阅读(226)  评论(0编辑  收藏  举报