pip3 install djangorestframework
認證類
認證源碼梳理
- 從rest_framework的dispatch開始入手觀察源碼
在dispatch中,對原生request進行了封裝
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 對原生的request進行加工,包含【原生request】豐富了authenticator
request = self.initialize_request(request, *args, **kwargs)
# 獲取原生的request對象 request._request
# 獲取認證類對象 request.authenticators
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
# 2. 認證
self.initial(request, *args, **kwargs)
.....
- 認證
跟進self.initial
def initial(self, request, *args, **kwargs):
self.format_kwarg = self.get_format_suffix(**kwargs)
'''版本處理'''
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
......
'''進行認證'''
self.perform_authentication(request)
'''權限控制'''
self.check_permissions(request)
'''訪問頻率'''
self.check_throttles(request)
然後繼續跟進,調用了.user._authenticate()方法 # 獲取認證對象進行一個一個認證,如果錯誤就觸發異常!
認證方法
這是
認證和視圖
寫在了一起,方便觀看,實際中最好將認證類單獨存放在一個py中
from rest_framework.views import APIView
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication # 內置的認證類【必須繼承】
class Authentication(BaseAuthentication): # 自己寫認證,然後引用
def authenticate(self, request):
token = request._request.GET.get('token')
token_obj = models.UserToken.objects.filter(token=token).first()
if not token_obj:
# 其實在內部捕捉了異常
raise exceptions.AuthenticationFailed('用戶認證失敗')
# 返回user對象 + token
# 在rest framework 內部會將兩個字段賦值給 request,給後面調用
'''返回值必須是元祖 第一個賦值給 request.user 第二個request.auth'''
return (token_obj.user, token_obj)
def authenticate_header(self, request):
pass
...
class DogView(APIView):
"""
應用上Authentication認證規則。如果有多個,那麼依次認證
如果都沒有認證,那麼默認值 request.user=AnonymousUser request.auth = None 匿名用戶
request.user 這是token_obj.user 源碼中規定元祖第一個
request.auth 這是token_obj 源碼中規定元祖第二個
"""
authentication_classes = [Authentication, ]
......
源碼流程圖
setting中配置認證類
實際中將自己寫的認證方法單獨放在一個py中,然後在項目setting中配置即可
# 導入自己寫的rest 認證路徑
"""
可以局部使用或者全局使用
局部: authentication_classes = []
"""
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ['app01.utils.auth.Authentication', ], # 全局使用的認證類,也可以局部使用
"UNAUTHENTICATED_USER": None, # 匿名用戶, request.user = None
"UNAUTHENTICATED_TOKEN": None, # 匿名用戶, request.auth = None
}
這樣寫的好處是無需再視圖中再寫引用了,會自動按照你setting中的配置進行認證,如果指定視圖不需要認證,那麼在該view中寫 authentication_classes = []
即可
內置的認證
- BaseAuthentication 主要使用的就是這個
- BasicAuthentication 瀏覽器內置的認證【大家瞭解下就是了】
- 剩下的就是基於django的用戶認證了
權限類
源碼流程與認證相似
- 必須繼承
BasePermission
並實現has_permission 方法
- massage = ‘自定義無權限的提示’
- 返回值: True or False 有權無權訪問
- setting中加入配置
REST_FRAMEWORK = {
# 權限和用戶認證同理
"DEFAULT_PERMISSION_CLASSES": ['app01.utils.permission.MyPermission', ], # 全局權限控制,也可以局部使用
}
from rest_framework.permissions import BasePermission # 儘量必須繼承
class MyPermission(BasePermission):
massage = '你沒有權限訪問'
def has_permission(self, request, view):
if request.user.user_type != 3:
return False
return True
使用總結
-
創建類: 繼承
BaseAuthentication
- 實現authenticate方法
-
返回值 結果 None 執行下一個認證 raise 認證失敗拋出異常 元祖(元素1,元素2) 元素1=request.user; 元素2=request.auth -
全局使用
setting中配置,然後在單獨的py文件中寫入認證「寫入路徑」
-
局部使用
在視圖中 引入authentication_classes = [認證類, ]