Django REST framework第二部分--------认证

Django REST framework是基于CBV模式实现的

Django REST framework和django的区别

先来看看认证部分
普通的CBV:

from django.views import View
class Eg(View):
    def get(self,request,*args,**kwargs):
        return HttpResponse("GET")

Django REST framework的CBV:

from rest_framework.views import APIView

class Eg(APIView):
    def get(self,request,*args,**kwargs):
        return HttpResponse("GET")

可以看出只是继承父类不同

查看APIView可发现class APIView(View),可以理解为APIview是对View的扩展或者是修改

Django REST framework自定义认证类使用示例

 路由:''re_path('^eg/$',views.Eg.as_view())''
 ''
 from rest_framework.views import APIView
 from rest_framework.authentication import BaseAuthentication
 class MyAuthenticate(BaseAuthentication):
 '''自定义认证类'''
  def authenticate(self,request):
      token=request._request.GET.get('token')  #request._request是原生request
      #token=request.query_params.get('token')   效果一样request._request.GET==request.query_params
      if not token:
          raise exceptions.AuthenticationFailed("用户登录失败")
      return ('yue',18)     #第一个元素通常是数据库表的一行数据,也就是一个类对象
 class Eg(APIView):
 '''视图'''
  authentication_classes = [MyAuthenticate,]     #局部使用自定义认证类
  def get(self,request,*args,**kwargs):
      print(request.user)        #认证类返回的元组的第一个元素
      return HttpResponse("GET")''
      
全局使用:REST_FRAMEWORK = {
               'DEFAULT_AUTHENTICATION_CLASSES': ('api.auth.MyAuthenticate'), #注意是认证类路径
               }

Django REST framework认证源码解析

首先,DRF一般都是CBV的模式。以普通视图为例(继承APIView,APIView继承了View,重写了dispatch方法,所以可以说DRF是对Django的一个扩展)。按生命周期开始,request到达之后,由wsgi解析请求信息,经过中间件,到达路由(re_path(’^eg/$’,views.Eg.as_view())),执行APIView的类方法as_view,在内部有执行父类View的类方法as_view,返回了一个view方法,变成了FBV模式(re_path(’^eg/$’,views.view)),view方法是View类里的内置方法,里面调用了self.dispatch(self.dispatch(request, *args, **kwargs)),根据继承关系,执行APIView的dispatch方法

 ''def dispatch(self, request, *args, **kwargs):
      self.args = args
      self.kwargs = kwargs
      request = self.initialize_request(request, *args, **kwargs)
      self.request = request
      self.headers = self.default_response_headers  # deprecate?
      try:
          self.initial(request, *args, **kwargs)
          # Get the appropriate handler method
          if request.method.lower() in self.http_method_names:
              handler = getattr(self, request.method.lower(),
                                self.http_method_not_allowed)
          else:
              handler = self.http_method_not_allowed
          response = handler(request, *args, **kwargs)
      except Exception as exc:
          response = self.handle_exception(exc)
      self.response = self.finalize_response(request, response, *args, **kwargs)
      return self.response''

首先看request = self.initialize_request(request,),执行APIView的initialize_request方法

 def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)

        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

返回的是一个Request类对象,其中对原生request做了封装和丰富,里面有原生request和别的
先看一下和认证相关的authenticators=self.get_authenticators()。

    def get_authenticators(self):
        """
        Instantiates and returns the list of authenticators that this view can use.
        """
        return [auth() for auth in self.authentication_classes]

返回的是一个类对象列表,

authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES

默认是一个Django REST framework配置文件类对象的列表,如果自己定义了authentication_classes 就用的自己的

然后回到dispatch继续往下走

 try:
            self.initial(request, *args, **kwargs)   #这里的request是处理后的,包含原生request,类对象列表和其他
     

initial方法里有self.perform_authentication(request)

perform_authentication方法内容

    def perform_authentication(self, request):
        """
        Perform authentication on the incoming request.

        Note that if you override this and simply 'pass', then authentication
        will instead be performed lazily, the first time either
        `request.user` or `request.auth` is accessed.
        """
        request.user

这里的request是Request类的一个对象,user是Request的一个静态方法,所以可以不加括号调用

    @property
    def user(self):
        """
        Returns the user associated with the current request, as authenticated
        by the authentication classes provided to the request.
        """
        if not hasattr(self, '_user'):
            with wrap_attributeerrors():
                self._authenticate()
        return self._user

再看_authenticate方法

    def _authenticate(self):
        """
        Attempt to authenticate the request using each authentication instance
        in turn.
        """
        for authenticator in self.authenticators:
            try:
                user_auth_tuple = authenticator.authenticate(self)
            except exceptions.APIException:
                self._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循环处理,self.authenticators就是authentication_classes类对象列表

这里以自定义认证类(可多个)为例:

循环执行每个认证类的authenticate方法:
1.抛异常,_authenticate捕获,raise继续往上抛
2.有返回值,必须是元组,包含两个元素(想返回什么都可以。一般第一个是数据库对象,方便后续直接使用),由self.user, self.auth = user_auth_tuple处理对应request.user,request.auth,可以在处理函数里面直接使用
3.没有返回值,默认返回None,执行下个认证类。都是None的话执行_not_authenticated,设置默认值,AnonymousUser和None(可在配置文件中修改)(UNAUTHENTICATED_USER=None, UNAUTHENTICATED_TOKEN=None)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值