restful(3):認證、權限、頻率
阿新 • • 發佈:2018-09-05
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):認證、權限、頻率