Django REST framework基礎:認證、權限、限制
阿新 • • 發佈:2019-04-15
bsp request history inf 機制 length pre div view
認證、權限和限制
身份驗證是將傳入請求與一組標識憑據(例如請求來自的用戶或其簽名的令牌)相關聯的機制。然後 權限 和 限制 組件決定是否拒絕這個請求。
簡單來說就是:
認證確定了你是誰
權限確定你能不能訪問某個接口
限制確定你訪問某個接口的頻率
認證
REST framework 提供了一些開箱即用的身份驗證方案,並且還允許你實現自定義方案。
接下類我們就自己動手實現一個基於Token的認證方案:
自定義Token認證
表
定義一個用戶表和一個保存用戶Token的表:
class UserInfo(models.Model): username= models.CharField(max_length=16) password = models.CharField(max_length=32) type = models.SmallIntegerField( choices=((1, ‘普通用戶‘), (2, ‘VIP用戶‘)), default=1 ) class Token(models.Model): user = models.OneToOneField(to=‘UserInfo‘) token_code = models.CharField(max_length=128)
定義一個登錄視圖:
def get_random_token(username): """ 根據用戶名和時間戳生成隨機token :param username: :return: """ import hashlib, time timestamp = str(time.time()) m = hashlib.md5(bytes(username, encoding="utf8")) m.update(bytes(timestamp, encoding="utf8"))return m.hexdigest() class LoginView(APIView): """ 校驗用戶名密碼是否正確從而生成token的視圖 """ def post(self, request): res = {"code": 0} print(request.data) username = request.data.get("username") password = request.data.get("password") user = models.UserInfo.objects.filter(username=username, password=password).first() if user: # 如果用戶名密碼正確 token = get_random_token(username) models.Token.objects.update_or_create(defaults={"token_code": token}, user=user) res["token"] = token else: res["code"] = 1 res["error"] = "用戶名或密碼錯誤" return Response(res)
定義一個認證類
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed class MyAuth(BaseAuthentication): def authenticate(self, request): if request.method in ["POST", "PUT", "DELETE"]: request_token = request.data.get("token", None) if not request_token: raise AuthenticationFailed(‘缺少token‘) token_obj = models.Token.objects.filter(token_code=request_token).first() if not token_obj: raise AuthenticationFailed(‘無效的token‘) return token_obj.user.username, None else: return None, None
視圖級別認證
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", ] }
權限
只有VIP用戶才能看的內容。
自定義一個權限類
# 自定義權限 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 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", ] }
限制
DRF內置了基本的限制類,首先我們自己動手寫一個限制類,熟悉下限制組件的執行過程。
自定義限制類
VISIT_RECORD = {} # 自定義限制 class MyThrottle(object): def __init__(self): self.history = None def allow_request(self, request, view): """ 自定義頻率限制60秒內只能訪問三次 """ # 獲取用戶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", ] }
使用內置限制類
from rest_framework.throttling import SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope = "xxx" def get_cache_key(self, request, view): return self.get_ident(request)
全局配置
# 在settings.py中設置rest framework相關配置項 REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ], # "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ] "DEFAULT_THROTTLE_CLASSES": ["app01.utils.VisitThrottle", ], "DEFAULT_THROTTLE_RATES": { "xxx": "5/m", } }
Django REST framework基礎:認證、權限、限制