DRF之三大認證
一、認證Authentication
認證主要用於登入認證,判斷使用者是否登入。在使用者登入時返回一個隨機的字串,之後再訪問時通過字串判斷使用者是否登入。
登入介面舉例:
編寫步驟:
建立user表和一對一userToken表,在前端傳入使用者名稱密碼,在後端接收去user表中對比,對比成功就讓他登入。
登入成功後在userToken表中記錄,並返回隨機字串,下次通過比對字串判斷是否登入。
models:
class User(models.Model): username = models.CharField(max_length=32) password= models.CharField(max_length=32) user_type = models.IntegerField(choices=((1, '超級管理員'), (2, '普通管理員'), (3, '普通使用者'))) # gender=models.IntegerField(choices=((1,"男"),(2,"女"),(0,"未知"))) # 1:男 2:女 0:未知 # user物件.get_欄位名_display() 快速取出gender數字對應的中文 class UserToken(models.Model): user = models.OneToOneField(to=User,on_delete=models.CASCADE) token= models.CharField(max_length=32)
views:
from rest_framework.viewsets import ViewSet from rest_framework.decorators import action from .models import User, UserToken import uuid from rest_framework.response import Response # class UserView(ViewSetMixin,APIView): class UserView(ViewSet): @action(methods=['POST'], detail=False) def login(self, request): username = request.data.get('username') password = request.data.get('password') user = User.objects.filter(username=username, password=password).first() if user: # 登陸成功--》生成一個隨機字串-->存到token表中(如果之前有記錄,更新,如果沒有新增) # uuid生成不重複的串---》理論上不重複 token = str(uuid.uuid4()) # 偽隨機數生成,沒有引數,重複概率,比其他的高一些 UserToken.objects.update_or_create(user=user, defaults={'token': token}) # 判斷user是否存在,如果存在就更新,如果不存在就新增 return Response({'code': 100, 'msg': '登陸成功', 'token': token}) else: return Response({'code': 101, 'msg': '使用者名稱或密碼錯誤'})
urls:
from django.contrib import admin from django.urls import path, include from app01 import views from rest_framework.routers import SimpleRouter router = SimpleRouter() router.register('user', views.UserView, 'user') urlpatterns = [ path('admin/', admin.site.urls), path('', include(router.urls)), ]
認證類:
完成登入介面之後就可編寫登入認證了:
編寫步驟:
寫一個類,繼承BaseAuthentication,重寫authenticate,在方法中做校驗,校驗是否登入,返回兩個值,沒有登入拋異常
新建一個auth.py:
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from .models import UserToken # 編寫認證類 # 全域性使用,區域性使用 # 步驟:寫一個類,繼承BaseAuthentication,重寫authenticate,在方法中做校驗,校驗是否登入,返回兩個值,沒有登入拋異常 class LoginAuth(BaseAuthentication): def authenticate(self, request): # 前端帶過來的token,放在哪,是介面(我們)固定的 token = request.query_params.get('token') user_token = UserToken.objects.filter(token=token).first() if user_token: # 登入了 # 第一個:當前登入使用者,第二個:token返回 return user_token.user, token else: # 丟擲認證失敗的異常 raise AuthenticationFailed('您沒有登入')
配置認證:
全域性配置方式:
可以在配置檔案中配置全域性預設的認證方案
REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.auth.LoginAuth",] }
區域性配置方式:
在檢視類中配置:
class UserView(ViewSet): authentication_classes = [LoginAuth]
區域性禁用:
在全域性配置後在指定的檢視類中配置:
class UserView(ViewSet): authentication_classes = []
二 許可權Permissions
許可權控制可以限制使用者對於檢視的訪問和對於具體資料物件的訪問。
-
- 在執行檢視的dispatch()方法前,會先進行檢視訪問許可權的判斷
- 在通過get_object()獲取具體物件時,會進行模型物件訪問許可權的判斷
許可權舉例:超級使用者才能增刪改,普通使用者只有查單條和多條的許可權。
編寫步驟:寫一個類,繼承BasePermission,重寫has_permission,判斷如果有許可權,返回True,如果沒有許可權,返回False
auth:
from rest_framework.permissions import BasePermission class UserPermission(BasePermission): def has_permission(self, request, view): self.message='您是:%s,沒有許可權'%request.user.get_user_type_display() # 沒有許可權的提示資訊 # 如果有許可權,返回True,沒有許可權返回False # 許可權類,在認證類之後,request.user有了當前登入使用者 user_type = request.user.user_type if user_type < 2: # 只要不是超級使用者,就沒有許可權 return True else: return False
將5個介面分在兩個檢視寫:
views:
# 普通使用者,只能檢視 from .auth import IPThrottle class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin): authentication_classes = [LoginAuth,] queryset = Book.objects.all() serializer_class = BookSerializer # 普通使用者以上,才能修改。。。 from .auth import UserPermission class BookDetailView(GenericViewSet, CreateModelMixin, DestroyModelMixin, UpdateModelMixin): authentication_classes = [LoginAuth, ] permission_classes = [UserPermission, ] queryset = Book.objects.all() serializer_class = BookSerializer
使用方式:
全域性使用:
可以在配置檔案中配置全域性預設的認證方案
REST_FRAMEWORK={ "DEFAULT_PERMISSION_CLASSES":["app01.auth.UserPermission",] }
區域性使用:
在檢視函式中配置:
class BookDetailView(GenericViewSet, CreateModelMixin, DestroyModelMixin, UpdateModelMixin): permission_classes = [UserPermission, ]
三、頻率
可以對介面訪問的頻次進行限制,以減輕伺服器壓力。
使用方式:寫一個類,繼承SimpleRateThrottle,重寫類屬性:scope,和get_cache_key方法
get_cache_key返回什麼,就以什麼做限制,scope配置檔案中要用
auth:
# 頻率限制類 from rest_framework.throttling import BaseThrottle,SimpleRateThrottle class IPThrottle(SimpleRateThrottle): scope = 'minute_3' # 隨便寫 # 返回什麼,就以什麼做現在 def get_cache_key(self, request, view): # 限制ip地址---》request.META字典---》請求頭中資料 return request.META.get('REMOTE_ADDR') # 客戶端ip # return request.user.id # 使用者id限制 class UserThrottle(SimpleRateThrottle): scope = 'minute_5' # 隨便寫 # 返回什麼,就以什麼做現在 def get_cache_key(self, request, view): return request.user.id
在配置檔案中配置:
'DEFAULT_THROTTLE_RATES': { 'minute_3': '3/m' # minute_3是scope的字串,一分鐘訪問3次 'minute_5':'5/m' }
區域性使用:
在檢視類中配置:
class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin): throttle_classes = [IPThrottle]
全域性使用:
在配置檔案中配置:
'DEFAULT_THROTTLE_CLASSES': ( # 全域性配置頻率類 'app01.auth.IPThrottle' ),