Django rest framework 許可權操作(原始碼分析二)
阿新 • • 發佈:2018-11-09
這一篇是基於上一篇寫的,上一篇謝了認證的具體流程,看懂了上一篇這一篇才能看懂,
當用戶訪問是 首先執行dispatch函式,當執行當第二部時:
#2.處理版本資訊 處理認證資訊 處理許可權資訊 對使用者的訪問頻率進行限制 self.initial(request, *args, **kwargs)
進入到initial方法:
def initial(self, request, *args, **kwargs): """ Runs anything that needs to occur prior to calling the method handler.""" self.format_kwarg = self.get_format_suffix(**kwargs) # Perform content negotiation and store the accepted info on the request neg = self.perform_content_negotiation(request) request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use.#2.1處理版本資訊 version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted #2.2處理認證資訊 self.perform_authentication(request)#2.3處理許可權資訊 self.check_permissions(request) #2.4對使用者的訪問頻率進行限制 self.check_throttles(request)
#2.3處理許可權資訊 self.check_permissions(request)
下面 開始 許可權的具體分析:
進入到check_permissions函式中
#檢查許可權 def check_permissions(self, request): """ Check if the request should be permitted. Raises an appropriate exception if the request is not permitted. """ #elf.get_permissions()得到的是一個許可權物件列表 for permission in self.get_permissions(): #在自定義的Permission中has_permission方法是必須要有的 #判斷當前has_permission返回的是True,False,還是丟擲異常 #如果是True則表示許可權通過,False執行下面程式碼 if not permission.has_permission(request, self): #為False的話則丟擲異常,當然這個異常返回的提示資訊是英文的,如果我們想讓他顯示我們自定義的提示資訊 #我們重寫permission_denied方法即可 self.permission_denied( #從自定義的Permission類中獲取message(許可權錯誤提示資訊),一般自定義的話都建議寫上,如果沒有則為預設的(英文提示) request, message=getattr(permission, 'message', None) )
檢視permission_denied方法(如果has_permission返回True則不執行該方法)
def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: #沒有登入提示的錯誤資訊 raise exceptions.NotAuthenticated() #一般是登陸了但是沒有許可權提示 raise exceptions.PermissionDenied(detail=message)
舉例:
from django.db import models # Create your models here. class Userinfo(models.Model): name=models.CharField(max_length=32,verbose_name='使用者名稱') pwd=models.CharField(max_length=32,verbose_name='密碼') token=models.CharField(max_length=64,null=True) def __str__(self): return self.namemodels
urlpatterns = [ url(r'^p/', app02_views.Pview.as_view()), url(r'^mp/', app02_views.Aview.as_view()), url(r'^jp/', app02_views.Jview.as_view()), ]urls
from django.shortcuts import render from rest_framework.views import APIView from rest_framework.authentication import BaseAuthentication from rest_framework.permissions import BasePermission from rest_framework.response import Response from rest_framework import exceptions from app01 import models # Create your views here. class MyAuthentication(BaseAuthentication): def authenticate(self, request): token=request.query_params.get('token') user=models.Userinfo.objects.filter(token=token).first() if user: return (user.name,user) return None class MyPermission(object): message = '登入才可以訪問' def has_permission(self,request, view): if request.user: return True return False class AdminPermission(object): message = '會員才可以訪問' def has_permission(self,request,view): if request.user=='ctz': return True return False class Pview(APIView): ''' 所有人都可以看 ''' authentication_classes = [MyAuthentication,] permission_classes = [] def get(self,request): return Response('圖片列表') def post(self,request): pass class Aview(APIView): ''' 登入的人可以看 ''' authentication_classes = [MyAuthentication,] permission_classes = [MyPermission,] def get(self,request): return Response('美國電影列表') def post(self,request): pass def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: raise exceptions.NotAuthenticated('無權訪問') raise exceptions.PermissionDenied(detail=message) class Jview(APIView): ''' 會員才可以看 ''' authentication_classes = [MyAuthentication,] permission_classes = [MyPermission,AdminPermission,] def get(self,request): return Response('日本電影列表') def post(self,request): pass def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: raise exceptions.NotAuthenticated('無權訪問') raise exceptions.PermissionDenied(detail=message)Views
上面的是區域性的只能在當前類中可以用,如果想在全域性中用:只需要在settings中配置即可:
from django.shortcuts import render from rest_framework.views import APIView from rest_framework.authentication import BaseAuthentication from rest_framework.permissions import BasePermission from rest_framework.response import Response from rest_framework import exceptions from app02.utils import MyPermission # # from app01 import models # # Create your views here. # # class MyAuthentication(BaseAuthentication): # # def authenticate(self, request): # token=request.query_params.get('token') # user=models.Userinfo.objects.filter(token=token).first() # if user: # return (user.name,user) # return None # # class MyPermission(object): # message = '登入才可以訪問' # def has_permission(self,request, view): # if request.user: # return True # return False # # class AdminPermission(object): # message = '會員才可以訪問' # def has_permission(self,request,view): # if request.user=='ctz': # return True # return False class Pview(APIView): ''' 所有人都可以看 ''' permission_classes = [] def get(self,request): return Response('圖片列表') def post(self,request): pass class Aview(APIView): ''' 登入的人可以看 ''' # authentication_classes = [MyAuthentication,] permission_classes = [MyPermission,] def get(self,request): return Response('美國電影列表') def post(self,request): pass def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: raise exceptions.NotAuthenticated('無權訪問') raise exceptions.PermissionDenied(detail=message) class Jview(APIView): ''' 會員才可以看 ''' # authentication_classes = [MyAuthentication,] # permission_classes = [MyPermission,AdminPermission,] def get(self,request): return Response('日本電影列表') def post(self,request): pass def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: raise exceptions.NotAuthenticated('無權訪問') raise exceptions.PermissionDenied(detail=message)Views
from django.shortcuts import render from rest_framework.authentication import BaseAuthentication from rest_framework.permissions import BasePermission from rest_framework.response import Response from rest_framework import exceptions from rest_framework.exceptions import APIException from app01 import models # Create your views here. class MyAuthentication(BaseAuthentication): def authenticate(self, request): token=request.query_params.get('token') user=models.Userinfo.objects.filter(token=token).first() if user: return (user.name,user) return None class MyPermission(object): message = '登入才可以訪問' def has_permission(self,request, view): if request.user: return True return False class AdminPermission(object): message = '會員才可以訪問' def has_permission(self,request,view): if request.user=='ctz': return True return Falseutils
REST_FRAMEWORK = { 'UNAUTHENTICATED_USER': None, 'UNAUTHENTICATED_TOKEN': None, "DEFAULT_AUTHENTICATION_CLASSES": [ # "app01.utils.MyAuthentication", "app02.utils.MyAuthentication", ], "DEFAULT_PERMISSION_CLASSES":[ "app02.utils.MyPermission", "app02.utils.AdminPermission", ], }settings
這一篇是基於上一篇寫的,上一篇謝了認證的具體流程,看懂了上一篇這一篇才能看懂,
當用戶訪問是 首先執行dispatch函式,當執行當第二部時:
#2.處理版本資訊 處理認證資訊 處理許可權資訊 對使用者的訪問頻率進行限制 self.initial(request, *args, **kwargs)
進入到initial方法:
def initial(self, request, *args, **kwargs): """ Runs anything that needs to occur prior to calling the method handler. """ self.format_kwarg = self.get_format_suffix(**kwargs) # Perform content negotiation and store the accepted info on the request neg = self.perform_content_negotiation(request) request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use. #2.1處理版本資訊 version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted #2.2處理認證資訊 self.perform_authentication(request) #2.3處理許可權資訊 self.check_permissions(request) #2.4對使用者的訪問頻率進行限制 self.check_throttles(request)
#2.3處理許可權資訊 self.check_permissions(request)
下面 開始 許可權的具體分析:
進入到check_permissions函式中
#檢查許可權 def check_permissions(self, request): """ Check if the request should be permitted. Raises an appropriate exception if the request is not permitted. """ #elf.get_permissions()得到的是一個許可權物件列表 for permission in self.get_permissions(): #在自定義的Permission中has_permission方法是必須要有的 #判斷當前has_permission返回的是True,False,還是丟擲異常 #如果是True則表示許可權通過,False執行下面程式碼 if not permission.has_permission(request, self): #為False的話則丟擲異常,當然這個異常返回的提示資訊是英文的,如果我們想讓他顯示我們自定義的提示資訊 #我們重寫permission_denied方法即可 self.permission_denied( #從自定義的Permission類中獲取message(許可權錯誤提示資訊),一般自定義的話都建議寫上,如果沒有則為預設的(英文提示) request, message=getattr(permission, 'message', None) )
檢視permission_denied方法(如果has_permission返回True則不執行該方法)
def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: #沒有登入提示的錯誤資訊 raise exceptions.NotAuthenticated() #一般是登陸了但是沒有許可權提示 raise exceptions.PermissionDenied(detail=message)
舉例:
from django.db import models # Create your models here. class Userinfo(models.Model): name=models.CharField(max_length=32,verbose_name='使用者名稱') pwd=models.CharField(max_length=32,verbose_name='密碼') token=models.CharField(max_length=64,null=True) def __str__(self): return self.namemodels
urlpatterns = [ url(r'^p/', app02_views.Pview.as_view()), url(r'^mp/', app02_views.Aview.as_view()), url(r'^jp/', app02_views.Jview.as_view()), ]urls
from django.shortcuts import render from rest_framework.views import APIView from rest_framework.authentication import BaseAuthentication from rest_framework.permissions import BasePermission from rest_framework.response import Response from rest_framework import exceptions from app01 import models # Create your views here. class MyAuthentication(BaseAuthentication): def authenticate(self, request): token=request.query_params.get('token') user=models.Userinfo.objects.filter(token=token).first() if user: return (user.name,user) return None class MyPermission(object): message = '登入才可以訪問' def has_permission(self,request, view): if request.user: return True return False class AdminPermission(object): message = '會員才可以訪問' def has_permission(self,request,view): if request.user=='ctz': return True return False class Pview(APIView): ''' 所有人都可以看 ''' authentication_classes = [MyAuthentication,] permission_classes = [] def get(self,request): return Response('圖片列表') def post(self,request): pass class Aview(APIView): ''' 登入的人可以看 ''' authentication_classes = [MyAuthentication,] permission_classes = [MyPermission,] def get(self,request): return Response('美國電影列表') def post(self,request): pass def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: raise exceptions.NotAuthenticated('無權訪問') raise exceptions.PermissionDenied(detail=message) class Jview(APIView): ''' 會員才可以看 ''' authentication_classes = [MyAuthentication,] permission_classes = [MyPermission,AdminPermission,] def get(self,request): return Response('日本電影列表') def post(self,request): pass def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: raise exceptions.NotAuthenticated('無權訪問') raise exceptions.PermissionDenied(detail=message)Views
上面的是區域性的只能在當前類中可以用,如果想在全域性中用:只需要在settings中配置即可:
from django.shortcuts import render from rest_framework.views import APIView from rest_framework.authentication import BaseAuthentication from rest_framework.permissions import BasePermission from rest_framework.response import Response from rest_framework import exceptions from app02.utils import MyPermission # # from app01 import models # # Create your views here. # # class MyAuthentication(BaseAuthentication): # # def authenticate(self, request): # token=request.query_params.get('token') # user=models.Userinfo.objects.filter(token=token).first() # if user: # return (user.name,user) # return None # # class MyPermission(object): # message = '登入才可以訪問' # def has_permission(self,request, view): # if request.user: # return True # return False # # class AdminPermission(object): # message = '會員才可以訪問' # def has_permission(self,request,view): # if request.user=='ctz': # return True # return False class Pview(APIView): ''' 所有人都可以看 ''' permission_classes = [] def get(self,request): return Response('圖片列表') def post(self,request): pass class Aview(APIView): ''' 登入的人可以看 ''' # authentication_classes = [MyAuthentication,] permission_classes = [MyPermission,] def get(self,request): return Response('美國電影列表') def post(self,request): pass def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: raise exceptions.NotAuthenticated('無權訪問') raise exceptions.PermissionDenied(detail=message) class Jview(APIView): ''' 會員才可以看 ''' # authentication_classes = [MyAuthentication,] # permission_classes = [MyPermission,AdminPermission,] def get(self,request): return Response('日本電影列表') def post(self,request): pass def permission_denied(self, request, message=None): """ If request is not permitted, determine what kind of exception to raise. """ if request.authenticators and not request.successful_authenticator: raise exceptions.NotAuthenticated('無權訪問') raise exceptions.PermissionDenied(detail=message)Views
from django.shortcuts import render from rest_framework.authentication import BaseAuthentication from rest_framework.permissions import BasePermission from rest_framework.response import Response from rest_framework import exceptions from rest_framework.exceptions import APIException from app01 import models # Create your views here. class MyAuthentication(BaseAuthentication): def authenticate(self, request): token=request.query_params.get('token') user=models.Userinfo.objects.filter(token=token).first() if user: return (user.name,user) return None class MyPermission(object): message = '登入才可以訪問' def has_permission(self,request, view): if request.user: return True return False class AdminPermission(object): message = '會員才可以訪問' def has_permission(self,request,view): if request.user=='ctz': return True return Falseutils
REST_FRAMEWORK = { 'UNAUTHENTICATED_USER': None, 'UNAUTHENTICATED_TOKEN': None, "DEFAULT_AUTHENTICATION_CLASSES": [ # "app01.utils.MyAuthentication", "app02.utils.MyAuthentication", ], "DEFAULT_PERMISSION_CLASSES":[ "app02.utils.MyPermission", "app02.utils.AdminPermission", ], }settings