04,认证、权限、频率
生活随笔
收集整理的這篇文章主要介紹了
04,认证、权限、频率
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?
認(rèn)證組件
Django原生的authentic組件為我們的用戶注冊(cè)與登錄提供了認(rèn)證功能,十分的簡介與強(qiáng)大。同樣DRF也為我們提供了認(rèn)證組件,一起來看看DRF里面的認(rèn)證組件是怎么為我們工作的! models.py # 定義一個(gè)用戶表和一個(gè)保存用戶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)15 1 # 定義一個(gè)用戶表和一個(gè)保存用戶Token的表 2 3 4 class UserInfo(models.Model): 5 ? ?username = models.CharField(max_length=16) 6 ? ?password = models.CharField(max_length=32) 7 ? ?type = models.SmallIntegerField( 8 ? ? ? ?choices=((1, '普通用戶'), (2, 'VIP用戶')), 9 ? ? ? ?default=1 10 ? ) 11 12 13 class Token(models.Model): 14 ? ?user = models.OneToOneField(to='UserInfo') 15 ? ?token_code = models.CharField(max_length=128) url path('login/', views.LoginView.as_view()),
1 1 ? ?path('login/', views.LoginView.as_view()), views.py # 視圖主要處理用戶名、密碼是否正確,用戶每一次請(qǐng)求都要帶著專有token來! import hashlib, time from rest_framework.response import Response from rest_framework.views import APIView def get_random_token(username): """ 根據(jù)用戶名和時(shí)間戳生成隨機(jī)token :param username: :return: """ timestamp = str(time.time()) m = hashlib.md5(bytes(username, encoding="utf8")) m.update(bytes(timestamp, encoding="utf8")) return m.hexdigest() class LoginView(APIView): """ 校驗(yàn)用戶名密碼是否正確從而生成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"] = "用戶名或密碼錯(cuò)誤" return Response(res)
38 1 # 視圖主要處理用戶名、密碼是否正確,用戶每一次請(qǐng)求都要帶著專有token來! 2 import hashlib, time 3 from rest_framework.response import Response 4 from rest_framework.views import APIView 5 6 7 def get_random_token(username): 8 ? ?""" 9 ? 根據(jù)用戶名和時(shí)間戳生成隨機(jī)token 10 ? :param username: 11 ? :return: 12 ? """ 13 ? ?timestamp = str(time.time()) 14 ? ?m = hashlib.md5(bytes(username, encoding="utf8")) 15 ? ?m.update(bytes(timestamp, encoding="utf8")) 16 ? ?return m.hexdigest() 17 18 19 class LoginView(APIView): 20 ? ?""" 21 ? 校驗(yàn)用戶名密碼是否正確從而生成token的視圖 22 ? """ 23 ? ?def post(self, request): 24 ? ? ? ?res = {"code": 0} 25 ? ? ? ?print(request.data) 26 ? ? ? ?username = request.data.get("username") 27 ? ? ? ?password = request.data.get("password") 28 29 ? ? ? ?user = models.UserInfo.objects.filter(username=username, password=password).first() 30 ? ? ? ?if user: 31 ? ? ? ? ? ?# 如果用戶名密碼正確 32 ? ? ? ? ? ?token = get_random_token(username) 33 ? ? ? ? ? ?models.Token.objects.update_or_create(defaults={"token_code": token}, user=user) 34 ? ? ? ? ? ?res["token"] = token 35 ? ? ? ?else: 36 ? ? ? ? ? ?res["code"] = 1 37 ? ? ? ? ? ?res["error"] = "用戶名或密碼錯(cuò)誤" 38 ? ? ? ?return Response(res) 定義認(rèn)證類model_serializer.py # 這一步是要對(duì)著源碼才能寫出來 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
18 1 # 這一步是要對(duì)著源碼才能寫出來 2 from rest_framework.authentication import BaseAuthentication 3 from rest_framework.exceptions import AuthenticationFailed 4 5 6 class MyAuth(BaseAuthentication): 7 ? ?def authenticate(self, request): 8 ? ? ? ?if request.method in ["POST", "PUT", "DELETE"]: 9 ? ? ? ? ? ?request_token = request.data.get("token", None) 10 ? ? ? ? ? ?if not request_token: 11 ? ? ? ? ? ? ? ?raise AuthenticationFailed('缺少token') 12 ? ? ? ? ? ?token_obj = models.Token.objects.filter(token_code=request_token).first() 13 ? ? ? ? ? ?if not token_obj: 14 ? ? ? ? ? ? ? ?raise AuthenticationFailed('無效的token') 15 ? ? ? ? ? ?return token_obj.user.username, None 16 ? ? ? ?else: 17 ? ? ? ? ? ?return None, None 18 全局配置 # 在settings.py中配置 REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ] }
4 1 # 在settings.py中配置 2 REST_FRAMEWORK = { 3 ? ?"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ] 4 }
權(quán)限組件
只有vip才能看的內(nèi)容 自定義權(quán)限類 # 自定義權(quán)限類 from rest_framework.permissions import BasePermission class MyPermission(BasePermission): message = 'VIP用戶才能訪問' def has_permission(self, request, view): """ 自定義權(quán)限只有VIP用戶才能訪問 """ # 因?yàn)樵谶M(jìn)行權(quán)限判斷之前已經(jīng)做了認(rèn)證判斷,所以這里可以直接拿到request.user if request.user and request.user.type == 2: # 如果是VIP用戶 return True else: return False15 1 # 自定義權(quán)限類 2 from rest_framework.permissions import BasePermission 3 4 class MyPermission(BasePermission): 5 ? ?message = 'VIP用戶才能訪問' 6 7 ? ?def has_permission(self, request, view): 8 ? ? ? ?""" 9 ? ? ? 自定義權(quán)限只有VIP用戶才能訪問 10 ? ? ? """ 11 ? ? ? ?# 因?yàn)樵谶M(jìn)行權(quán)限判斷之前已經(jīng)做了認(rèn)證判斷,所以這里可以直接拿到request.user 12 ? ? ? ?if request.user and request.user.type == 2: ?# 如果是VIP用戶 13 ? ? ? ? ? ?return True 14 ? ? ? ?else: 15 ? ? ? ? ? ?return False 視圖級(jí)別配置 class CommentViewSet(ModelViewSet): queryset = models.Comment.objects.all() serializer_class = app01_serializers.CommentSerializer authentication_classes = [MyAuth, ] permission_classes = [MyPermission, ]
6 1 class CommentViewSet(ModelViewSet): 2 3 ? ?queryset = models.Comment.objects.all() 4 ? ?serializer_class = app01_serializers.CommentSerializer 5 ? ?authentication_classes = [MyAuth, ] 6 ? ?permission_classes = [MyPermission, ] 全局配置 REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ], "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ] }
4 1 REST_FRAMEWORK = { 2 ? ?"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ], 3 ? ?"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ] 4 }
頻率組件
頻率:限制用戶訪問網(wǎng)站的頻率 自定義限制類 VISIT_RECORD = {} # 自定義限制 class MyThrottle(object): def __init__(self): self.history = None def allow_request(self, request, view): """ 自定義頻率限制60秒內(nèi)只能訪問三次 """ # 獲取用戶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): """ 限制時(shí)間還剩多少 """ timestamp = time.time() return 60 - (timestamp - self.history[-1])33 1 VISIT_RECORD = {} 2 # 自定義限制 3 class MyThrottle(object): 4 5 ? ?def __init__(self): 6 ? ? ? ?self.history = None 7 8 ? ?def allow_request(self, request, view): 9 ? ? ? ?""" 10 ? ? ? 自定義頻率限制60秒內(nèi)只能訪問三次 11 ? ? ? """ 12 ? ? ? ?# 獲取用戶IP 13 ? ? ? ?ip = request.META.get("REMOTE_ADDR") 14 ? ? ? ?timestamp = time.time() 15 ? ? ? ?if ip not in VISIT_RECORD: 16 ? ? ? ? ? ?VISIT_RECORD[ip] = [timestamp, ] 17 ? ? ? ? ? ?return True 18 ? ? ? ?history = VISIT_RECORD[ip] 19 ? ? ? ?self.history = history 20 ? ? ? ?history.insert(0, timestamp) 21 ? ? ? ?while history and history[-1] < timestamp - 60: 22 ? ? ? ? ? ?history.pop() 23 ? ? ? ?if len(history) > 3: 24 ? ? ? ? ? ?return False 25 ? ? ? ?else: 26 ? ? ? ? ? ?return True 27 28 ? ?def wait(self): 29 ? ? ? ?""" 30 ? ? ? 限制時(shí)間還剩多少 31 ? ? ? """ 32 ? ? ? ?timestamp = time.time() 33 ? ? ? ?return 60 - (timestamp - self.history[-1]) 視圖級(jí)別配置 class CommentViewSet(ModelViewSet): queryset = models.Comment.objects.all() serializer_class = app01_serializers.CommentSerializer throttle_classes = [MyThrottle, ]
x 1 class CommentViewSet(ModelViewSet): 2 3 ? ?queryset = models.Comment.objects.all() 4 ? ?serializer_class = app01_serializers.CommentSerializer 5 ? ?throttle_classes = [MyThrottle, ] 全局配置 # 在settings.py中設(shè)置rest framework相關(guān)配置項(xiàng) REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ], "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ] "DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ] }
1 # 在settings.py中設(shè)置rest framework相關(guān)配置項(xiàng) 2 REST_FRAMEWORK = { 3 ? ?"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ], 4 ? ?"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ] 5 ? ?"DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ] 6 }
認(rèn)證組件的源碼閱讀
?
新構(gòu)建的request里面的源碼的user方法
?
源碼走到了這里其實(shí)就已經(jīng)需要我們自己來進(jìn)行認(rèn)證了。就可以對(duì)前端的請(qǐng)求進(jìn)行認(rèn)證,到底該怎么認(rèn)證,還得繼續(xù)往下走!
?權(quán)限組件的源碼閱讀
相比較與認(rèn)證組件,權(quán)限組件就更加的簡潔了
頻率組件的注意部分
轉(zhuǎn)載于:https://www.cnblogs.com/pontoon/p/10217414.html
總結(jié)
以上是生活随笔為你收集整理的04,认证、权限、频率的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode Golang 9.回
- 下一篇: Leetcode 565. Array