rest_framework学习之认证

在讲reat_frameworkd的认证前,我们先来看看Django原生的类视图(django.views.View)的运行过程是怎么样的:

wwsgi --> 中间件(Middleware) -->url路由解析 --> 类视图的as_view方法 --> view方法 --> dispath方法 --> 反射对应的请求方法的函数并执行

一、 在rest_framework中提供了APIView,重写了View的dispatch方法,我们可以从源码中看出,在执行dispath方法的时又执行了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
	#版本解析
	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)
二、 认证步骤中执行了perform_authentication方法进而又执行了request(在原生的request上装饰过的)的user方法:
def perform_authentication(self, request):
	request.user
三、 接着运行了_authenticate方法
@property
def user(self):
	if not hasattr(self, '_user'):
		with wrap_attributeerrors():
			self._authenticate()  # 主要的认证函数
	return self._user
四、 在_authenticate方法中,将self.authenticators的每一个认证类进行实例化,并执行认证类的authenticate方法。当认证出错时又执行self._not_authenticated方法。
def _authenticate(self):
	for authenticator in self.authenticators:  # 取出self.authenticators的每一个认证类
		try:
			user_auth_tuple = authenticator.authenticate(self)  # 执行认证类的authenticate方法
		except exceptions.APIException:
			self._not_authenticated()  # 认证失败时执行_not_authenticated方法
			raise

		if user_auth_tuple is not None:
			self._authenticator = authenticator
			self.user, self.auth = user_auth_tuple
			return

	self._not_authenticated()
五、 self.authenticators是request的属性,在执行APIView的dispatch方法时对原生的request封装了你在类视图中添加的authentication_classes属性,遍历并将它们存放在request的authenticators属性中:
def dispatch(self, request, *args, **kwargs):
	"""部分内容省略"""
	request = self.initialize_request(request, *args, **kwargs)
  • APIView的initialize_request方法又实例化了Request对象,将解析、认证等信息封装在request中,其中self.get_authenticators()就是封装认证类的方法:
def initialize_request(self, request, *args, **kwargs):
	parser_context = self.get_parser_context(request)
	return Request(
		request,
		parsers=self.get_parsers(),
		authenticators=self.get_authenticators(),  # 将认证类封装到request的authenticators中()
		negotiator=self.get_content_negotiator(),
		parser_context=parser_context
	)
  • self.get_authenticators()方法简单的将authentication_classes的每一个对象实例化并返回,赋值到authenticators中,Request会将认证类又赋值到self.authenticators中,供认证的时候使用:
def get_authenticators(self):
	return [auth() for auth in self.authentication_classes]
六、 authentication_classes在APIView类的属性中出现,若继承了APIView的自定义类中出现了authentication_classes,会取自定义的authentication_classes列表而不是APIView内置的。因此我们在为视图准备认证方法的时候,可以在类视图中添加authentication_classes属性,用列表的形式将需要视图需要使用的认证类放在里面:
from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication, BasicAuthentication

class MyVIew(APIView):
	authentication_classes = [BaseAuthentication, BasicAuthentication]  # 使用了rest_framework内置的认证类
	…………

rest_framework内置了五种认证类:BaseAuthentication、BasicAuthentication、SessionAuthentication、TokenAuthentication、RemoteUserAuthentication。

七、 当然我们可以自定义认证类,然后把它们放在视图的authentication_classes中,但是认证类必须包含两个方法,即authenticate和authenticate_header:
from user.models import UserToken
from rest_framework import exceptions

class MyAuthentication(BaseAuthentication):
    def authenticate(self, request):
        token = request._request.GET.get('token')
		try:
			usertoken = UserToken.objects.get(token=token)
		except UserToken.DoesNotExist:
			msg = _('请登录后访问')
			raise exceptions.AuthenticationFailed(msg)
			
		return usertoken.user, none
		
    def authenticate_header(self, request):
        pass

authenticate有返回的内容有三种情况:1. 返回一个元组(user, auth),代表认证成功,最终这两个对象会赋值到request的user和auth中;2. 认证成功后返回(none, none),代表匿名访问;3. 认证错误抛出异常AuthenticationFailed,可以定制message来指定认证失败后的返回的信息。authenticate_header方法可以不填写内容

八、 如果视图中设置authentication_classes,则为局部认证类,我们还可以为整个项目设置全局认证,即在项目的settings.py中添加以下配置:
REST_FRAMEWORK = {
	# 以列表的形式,将视图类的路径填写在AUTHENTICATION_CLASSES里,这里的认证类将影响所以视图
    "AUTHENTICATION_CLASSES": ['rest_framework.authentication.BaseAuthentication']
}

当部分视图需要使用其他的认证类时,可以在视图添加authentication_classes属性来覆盖全局配置的视图类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值