认证组件,权限组件,频率组件,控制版本

认证组件 
1 写一个认证类
from rest_framework.authentication import BaseAuthentication
class MyAuth(BaseAuthentication):
def authenticate(self,request):
# request 是封装后的
token = request.query_params.get('token')
ret = models.UserToken.objects.filter(token=token).first()
if ret:
# 认证通过
return
else:
raise AuthenticationFailed('认证失败')
#可以不写了
def authenticate_header(self,ss):
pass
2 局部使用
authentication_classes=[MyAuth,MyAuth2]
3 全局使用
查找顺序:自定义的APIView里找---》项目settings里找---》内置默认的
REST_FRAMEWORK={
'DEFAULT_AUTHENTICATION_CLASSES':['utils.common.MyAuth',]

}


权限组件 
1 写一个类
from rest_framework.permissions import BasePermission
class MyPermission(BasePermission):
message = '不是超级用户,查看不了'
def has_permission(self,request,view):
token=request.query_params.get('token')
ret=models.UserToken.objects.filter(token=token).first()
if ret.user.type==2:
# 超级用户可以访问
return True
else:
return False
2 局部使用:
permission_classes=[MyPermission,]
3 全局使用:
REST_FRAMEWORK={
'DEFAULT_PERMISSION_CLASSES':['utils.common.MyPermission',]
}

频率组件 
1 写一个类:
from rest_framework.throttling import SimpleRateThrottle
class VisitThrottle(SimpleRateThrottle):
scope = 'xxx'
def get_cache_key(self, request, view):
return self.get_ident(request)
2 在setting里配置:
'DEFAULT_THROTTLE_RATES':{
'xxx':'5/h',
}
3 局部使用
throttle_classes=[VisitThrottle,]
4 全局使用
REST_FRAMEWORK={
'DEFAULT_THROTTLE_CLASSES':['utils.common.VisitThrottle',]
}

认证,想局部取消(禁用)比如login登录的时候就需要禁用掉认证
authentication_classes=[]

认证组件 不存数据库的token验证

视图层:

def get_token(id,salt='123'):
    import hashlib
    md=hashlib.md5()
    md.update(bytes(str(id),encoding='utf-8'))
    md.update(bytes(salt,encoding='utf-8'))

    return md.hexdigest()+'|'+str(id)

def check_token(token,salt='123'):
    ll=token.split('|')
    import hashlib
    md=hashlib.md5()
    md.update(bytes(ll[-1],encoding='utf-8'))
    md.update(bytes(salt,encoding='utf-8'))
    if ll[0]==md.hexdigest():
        return True
    else:
        return False

class TokenAuth():
    def authenticate(self, request):
        token = request.GET.get('token')
        success=check_token(token)
        if success:
            return
        else:
            raise AuthenticationFailed('认证失败')
    def authenticate_header(self,request):
        pass
class Login(APIView):
    def post(self,reuquest):
        back_msg={'status':1001,'msg':None}
        try:
            name=reuquest.data.get('name')
            pwd=reuquest.data.get('pwd')
            user=models.User.objects.filter(username=name,password=pwd).first()
            if user:
                token=get_token(user.pk)
                # models.UserToken.objects.update_or_create(user=user,defaults={'token':token})
                back_msg['status']='1000'
                back_msg['msg']='登录成功'
                back_msg['token']=token
            else:
                back_msg['msg'] = '用户名或密码错误'
        except Exception as e:
            back_msg['msg']=str(e)
        return Response(back_msg)
from rest_framework.authentication import BaseAuthentication
class TokenAuth():
    def authenticate(self, request):
        token = request.GET.get('token')
        token_obj = models.UserToken.objects.filter(token=token).first()
        if token_obj:
            return
        else:
            raise AuthenticationFailed('认证失败')
    def authenticate_header(self,request):
        pass

class Course(APIView):
    authentication_classes = [TokenAuth, ]

    def get(self, request):
        return HttpResponse('get')

    def post(self, request):
        return HttpResponse('post')
View Code

频率组件

2 频率:
    django自带了频率控制类,比如是flask没有这种类的话需要自己写频率控制类
    为了控制用户对某个url请求的频率,比如,一分钟以内,只能访问三次
    自定义的逻辑

    #(1)取出访问者ip
    # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
    # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
    # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
    # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败

视图层:    
class MyThrottles():
    VISIT_RECORD = {}
    def __init__(self):
        self.history=None
    def allow_request(self,request, view):
        #(1)取出访问者ip
        # print(request.META)
        ip=request.META.get('REMOTE_ADDR')
        import time
        ctime=time.time()
        # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问
        if ip not in self.VISIT_RECORD:
            self.VISIT_RECORD[ip]=[ctime,]
            return True
        self.history=self.VISIT_RECORD.get(ip)
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        while self.history and ctime-self.history[-1]>60:
            self.history.pop()
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        if len(self.history)<3:
            self.history.insert(0,ctime)
            return True
        else:
            return False
    def wait(self):
        import time
        ctime=time.time()
        return 60-(ctime-self.history[-1])


    2.1自定义: 
        1 定义一个类MyThrottles
            allow_request(频率限制的逻辑)
            wait(返回一个数字,给用户提示,还差多少秒)
        2 局部使用:throttle_classes=[MyThrottles,]
        3 全局使用:'DEFAULT_THROTTLE_CLASSES':['utils.common.MyThrottles',],

        
    2.2用内置的:(可以控制ip,和userid)    
    from rest_framework.throttling import SimpleRateThrottle
    class VisitThrottle(SimpleRateThrottle):
        scope = 'xxx'
        def get_cache_key(self, request, view):
            # 这里可以写按照用户或者ip来限制频率
            # ip=rquest.META.get('REMOTE_ADDR')
            pk = request.user.pk
            return pk
            # return self.get_ident(request)
            
        1 写一个类,继承SimpleRateThrottle
            属性:scope = 'xxx'
            重写方法:get_cache_key
            去setting里配置:'DEFAULT_THROTTLE_RATES':{
                                # 'xxx':'5/m',
                                'xxx':'5/m',
                            }        
        2 局部使用:throttle_classes=[MyThrottles,]
        3 全局使用:'DEFAULT_THROTTLE_CLASSES':['utils.common.MyThrottles',],
        

错误信息的中文提示:        
class Course(APIView):
    authentication_classes = [TokenAuth, ]
    permission_classes = [UserPermission, ]
    throttle_classes = [MyThrottles,]

    def get(self, request):
        return HttpResponse('get')

    def post(self, request):
        return HttpResponse('post')
    def throttled(self, request, wait):
        from rest_framework.exceptions import Throttled
        class MyThrottled(Throttled):
            default_detail = '傻逼啊'
            extra_detail_singular = '还有 {wait} second.'
            extra_detail_plural = '出了 {wait} seconds.'
        raise MyThrottled(wait)
View Code

版本控制: 取不同url中的版本

    url:
    url(r'^testversion/', views.Test.as_view()),
    url(r'^(?P<version>[v1|v2|v3]+)/testversion/', views.Test2.as_view(),name='ttt'),
    
    视图:
    from django.shortcuts import render,HttpResponse

    # Create your views here.

    from rest_framework.views import APIView

    from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning
    class Test(APIView):
        versioning_class = QueryParameterVersioning
        def get(self,request,*args,**kwargs):
            print(request.version)
            return HttpResponse('ok')

    from django.urls import reverse
    class Test2(APIView):
        versioning_class = URLPathVersioning
        def get(self,request,*args,**kwargs):
            print(request.version)
            url=request.versioning_scheme.reverse(viewname='ttt',request=request)
            print(url)
            url2=reverse(viewname='ttt',kwargs={'version':'v1'})
            print(url2)
            return HttpResponse('ok')

    
    1 127.0.0.1/course/?version=v100000
        路由:
        url(r'^testversion/', views.Test.as_view()),
        视图层:
      用from rest_framework.versioning import QueryParameterVersioning
      class Test(APIView):
        versioning_class = QueryParameterVersioning
        def get(self,request,*args,**kwargs):
            print(request.version)
            return HttpResponse('ok')
      在视图类里:
        versioning_class=QueryParameterVersioning(**不再是列表)
      在setting里配置:
        REST_FRAMEWORK={
            'VERSION_PARAM':'version',
            'DEFAULT_VERSION':'v2',
            'ALLOWED_VERSIONS':['v1','v2']
        }
      取:
            视图类里:
            request.version
    
    127.0.0.1/v1/course/
    
          用from rest_framework.versioning import URLPathVersioning
          在视图类里:
            versioning_class=URLPathVersioning**不再是列表)
          在setting里配置:
            REST_FRAMEWORK={
                'VERSION_PARAM':'version',
                'DEFAULT_VERSION':'v2',
                'ALLOWED_VERSIONS':['v1','v2']
            }
          取:
            视图类里:
            request.version

    3 反向解析(了解)
View Code
原文地址:https://www.cnblogs.com/xujinjin18/p/9833923.html