rest_framework學習之“權限”

今天我們來看看rest_framework的APIView的權限驗證過程是怎麼走的。

一、 與認證的入口相似,權限驗證也是從APIView的dispatch()到initial()方法,再到check_permissions(),通過返回True或者False來判斷請求是否通過了權限驗證:
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
	version, scheme = self.determine_version(request, *args, **kwargs)
	request.version, request.versioning_scheme = version, scheme
	# 認證
	self.perform_authentication(request)
	# 權限
	self.check_permissions(request)
	# 節流
	self.check_throttles(request)
二、 在check_permissions方法中,遍歷了視圖的get_permissions方法的返回值(返回的是列表形式存儲的權限驗證類的實例),並運行它們的has_permission方法。
def check_permissions(self, request):
	for permission in self.get_permissions():  # get_permissions方法返回了權限類的列表推導式
		if not permission.has_permission(request, self):  # 遍歷權限類並執行has_permission方法
			self.permission_denied(
				request, message=getattr(permission, 'message', None)
	)
  • get_permissions從定義的視圖中拿到permission_classes(列表格式,可包含多個權限類),並使用列表推導式將實例化的對象存放在列表並返回給check_permissions使用。
def get_permissions(self):
	return [permission() for permission in self.permission_classes]
三、 如果權限類的has_permission返回True,那麼本次循環不做任何操作,繼續執行下一個權限類的has_permission方法。如果全部返回True,那麼本次權限驗證全部通過,否則執行視圖的permission_denied方法,
def permission_denied(self, request, message=None):
	if request.authenticators and not request.successful_authenticator:
		raise exceptions.NotAuthenticated()
	raise exceptions.PermissionDenied(detail=message)  # 拋出權限拒絕的錯誤

可以在視圖類中添加message屬性來定製權限驗證失敗後返回的信息。

四、 由APIView源碼可以知道,權限類可以在視圖類的permission_classes中設定,以列表的格式。
from rest_framework.permissions import AllowAny
from rest_framework.authentication import BaseAuthentication

class MyView(APIView):
	authentication_classes = [BaseAuthentication,]  # 認證類
	permission_classes = [AllowAny,]  # 權限類
	def get(self, request, *args, **kwargs):
		…………

rest_framework中內置了8中認證類:BasePermission、AllowAny、IsAuthenticated、IsAdminUser、IsAuthenticatedOrReadOnly、DjangoModelPermissions、DjangoModelPermissionsOrAnonReadOnly、DjangoObjectPermissions。

五、 與認證類同理,權限類如果設置在項目的配置文件中,就有了全局權限驗證的效果:
REST_FRAMEWORK = {
	"DEFAULT_AUTHENTICATION_CLASSES": ["rest_framework.authentication.BaseAuthentication",],  # 認證類
	"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.AllowAny"]  # 權限類
}
六、 如果想要自定義權限類,必須包含兩個方法:has_permission(self, request, view)、has_object_permission(self, request, view, obj)。注意:方法中傳遞的參數也是不可省略的。
class Mypermissions(object):
	def has_permission(self, request, view):
		# VIP用戶方可訪問
		if request.user.group == 'VIP':
			return True
		return False
		
	def has_object_permission(self, request, view, obj):
		return True
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章