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", ] }
############### 结束线 ###############
技术改变命运