1. 程式人生 > >restful(3):認證、權限、頻率

restful(3):認證、權限、頻率

col 數據 ges dom base print miss lte efi

models.py中:

class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    psw = models.CharField(max_length=32)
    user_type_choices = ((1,"普通"),(2,"VIP"),(3,"SVIP"))
    user_type = models.SmallIntegerField(choices=user_type_choices,default=1)  # 新添加一個標識用戶權限級別的字段

class Token(models.Model):  #
Token類用於 認證 user = models.OneToOneField(to="UserInfo",on_delete=models.CASCADE) token = models.CharField(max_length=128)

認證組件:

局部視圖認證:

在app01.service.auth.py:

class Authentication(BaseAuthentication):

    def authenticate(self,request):  # authenticate()  這個方法名是固定的
        token=request._request.GET.get("
token") token_obj=UserToken.objects.filter(token=token).first() if not token_obj: # 檢查token是否存在 raise exceptions.AuthenticationFailed("驗證失敗!") # 認證失敗時的固定語法 return (token_obj.user,token_obj) # 認證成功後需要返回一個元組:第一個是用戶有關的信息

在views.py:

def get_random_str(user):
    
import hashlib,time ctime=str(time.time()) md5=hashlib.md5(bytes(user,encoding="utf8")) # user是為了“加鹽”處理 md5.update(bytes(ctime,encoding="utf8")) return md5.hexdigest() from app01.service.auth import * from django.http import JsonResponse class LoginViewSet(APIView): authentication_classes = [Authentication,] # authentication_classes 是固定寫法;需要認證的類都寫在後面的列表中 def post(self,request,*args,**kwargs): res={"code":1000,"msg":None} try: user=request._request.POST.get("user") pwd=request._request.POST.get("pwd") user_obj=UserInfo.objects.filter(user=user,pwd=pwd).first() print(user,pwd,user_obj) if not user_obj: res["code"]=1001 res["msg"]="用戶名或者密碼錯誤" else: token=get_random_str(user) UserToken.objects.update_or_create(user=user_obj,defaults={"token":token}) # 表中沒有就創建,有就更新;# 返回一個元組:第一個是對象,第二個是布爾值(表示create還是update) res["token"]=token except Exception as e: res["code"]=1002 res["msg"]=e return JsonResponse(res,json_dumps_params={"ensure_ascii":False}) # {"ensure_ascii":False} 作用:顯示中文

全局視圖認證組件:

settings.py配置如下:

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",]  # 寫上 認證類的路徑
}

權限組件

局部視圖權限

在app01.service.permissions.py中:

from rest_framework.permissions import BasePermission
class SVIPPermission(BasePermission):
    message="SVIP才能訪問!"  # 沒有權限時返回的錯誤信息
    def has_permission(self, request, view):
        if request.user.user_type==3:
            return True
        return False  

# return True就是通過權限認證, return False 即沒有權限

在views.py:

from app01.service.permissions import *

class BookViewSet(generics.ListCreateAPIView):
    permission_classes = [SVIPPermission,]  # permission_classes 是固定寫法;需要校驗的權限類都寫在後面的列表中(這是局部權限校驗)
    queryset = Book.objects.all()
    serializer_class = BookSerializers

全局視圖權限:

settings.py配置如下:

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
    "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",]  # 寫上權限認證類的路徑
}

throttle(訪問頻率)組件

局部視圖throttle

在app01.service.throttles.py中:

from rest_framework.throttling import BaseThrottle

VISIT_RECORD={}
class VisitThrottle(BaseThrottle):

    def __init__(self):
        self.history=None

    def allow_request(self,request,view):  # allow_request()是固定的方法名

        # 以下為業務邏輯(rest 只處理數據,不處理邏輯)
        remote_addr = request.META.get(REMOTE_ADDR)  # 客戶端的IP地址
        print(remote_addr)
        import time
        ctime=time.time()

        if remote_addr not in VISIT_RECORD:
            VISIT_RECORD[remote_addr]=[ctime,]
            return True

        history=VISIT_RECORD.get(remote_addr)
        self.history=history

        while history and history[-1]<ctime-60:
            history.pop()

        if len(history)<3:
            history.insert(0,ctime)
            return True # return True 表示通過驗證
        else:
            return False  # return False 表示沒通過驗證

    def wait(self):
        import time
        ctime=time.time()
        return 60-(ctime-self.history[-1])

在views.py中:

from app01.service.throttles import *

class BookViewSet(generics.ListCreateAPIView):
    throttle_classes = [VisitThrottle,]  # throttle_classes 是固定寫法;
    queryset = Book.objects.all()
    serializer_class = BookSerializers

全局視圖throttle

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
    "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
    "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",]
}

內置throttle類

在app01.service.throttles.py修改為:

class VisitThrottle(SimpleRateThrottle):

    scope="visit_rate"
    def get_cache_key(self, request, view):

        return self.get_ident(request)

settings.py設置:

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
    "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
    "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",],
    "DEFAULT_THROTTLE_RATES":{
        "visit_rate":"5/m",
    }
}

restful(3):認證、權限、頻率