DRF-基于APIView的认证流程

rest framework框架

  • 我们来看一段伪代码,MyClassView继承了APIView就有了APIView的功能
class APIView(View):
    pass 


class MyClassView(APIView):
    pass
  • 基于Django的CBV
from django.views import View
from django.http import HttpResponse


class MyClassView(View):
    def get(self, request, *args, **kwargs):
        ret = {
            "state_code": 1000,
            "msg": "successful"
        }
        import json
        return HttpResponse(json.dumps(ret), status=201)

    def post(self, request, *args, **kwargs):
        return HttpResponse("created successful")

    def delete(self, request, *args, **kwargs):
        return HttpResponse("delete successful")
  • 基于DRF的CBV ,DRF的APIView在Django的View基础上,增加和丰富了一些功能
from django.views import View
from django.http import HttpResponse
from rest_framework.views import APIView


class MyClassView(APIView):
    def get(self, request, *args, **kwargs):
        ret = {
            "state_code": 1000,
            "msg": "successful"
        }
        import json
        return HttpResponse(json.dumps(ret), status=201)

    def post(self, request, *args, **kwargs):
        return HttpResponse("created successful")

    def delete(self, request, *args, **kwargs):
        return HttpResponse("delete successful")

原理(流程)

  • 当请求进来,先找CBV里面的dispatch方法
"""
rest_framework\views.py 
"""

 def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        # 对原生的request进行加工(丰富了一些功能)
        request = self.initialize_request(request, *args, **kwargs)
        # 获取原生request,request._request
        # 获取认证类的对象,request.authenticators
        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
  • 反射
DRF-基于APIView的认证流程
微信截图_20190108191829
  • request加强
DRF-基于APIView的认证流程
微信截图_20190108200309
  • self.initialize_request方法做了什么?
DRF-基于APIView的认证流程
微信截图_20190108200451

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

# 加工后新生成了Request对象
return Request(
    request,  # 原本的那个request
    parsers=self.get_parsers(),
    authenticators=self.get_authenticators(), # 认证相关
    negotiator=self.get_content_negotiator(),
    parser_context=parser_context
)
  • self.get_authenticators()方法
DRF-基于APIView的认证流程
微信截图_20190108201228
def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
# self.authentication_classes = [Dog,Cat]   auth()就是Dog和Cat对象,被装进列表里面 
return [auth() for auth in self.authentication_classes]
  • get_authenticators()方法中的self.authentication_classes,先从当前类找,有就使用当前类的authentication_classes,没有就使用父类的authentication_classes,在这里使用的是APIView里面的
DRF-基于APIView的认证流程
微信截图_20190108201739
DRF-基于APIView的认证流程
微信截图_20190108202231
  • 回到dispatch方法,我们可以看到其实request对象里面就有原生request和[BasicAuthentication,]
DRF-基于APIView的认证流程
微信截图_20190108203020
  • 拿到原生request方法
DRF-基于APIView的认证流程
微信截图_20190108203935
  • 获取认证类的对象,request.authenticators和原生request
DRF-基于APIView的认证流程
微信截图_20190108204355
  • 我们可以查看dispatch方法里面的反射前做了是什么,self.initial方法
DRF-基于APIView的认证流程
微信截图_20190108204819
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.
    version, scheme = self.determine_version(request, *args, **kwargs)
    request.version, request.versioning_scheme = version, scheme

    # Ensure that the incoming request is permitted
    self.perform_authentication(request)
    self.check_permissions(request)
    self.check_throttles(request)
DRF-基于APIView的认证流程
微信截图_20190108205218
  • 父类的perform_authentication()方法
DRF-基于APIView的认证流程
微信截图_20190108205348
DRF-基于APIView的认证流程
微信截图_20190108205626
  • 找到user
DRF-基于APIView的认证流程
微信截图_20190108205727
# _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()
DRF-基于APIView的认证流程
微信截图_20190108210210

登陆认证

  • 我们可以编写一个自己的认证类
class MyAuthentication(object):
    def authenticate(self, request):
        token = request._request.GET.get('token')
        if not token:
            from rest_framework import exceptions
            raise exceptions.AuthenticationFailed("对不起,用户认证失败")
        return ("zhangsan", None)

  • postman验证
DRF-基于APIView的认证流程
微信截图_20190108211046
DRF-基于APIView的认证流程
微信截图_20190108211238
  • 解决报错
DRF-基于APIView的认证流程
微信截图_20190108211347
  • postman验证
DRF-基于APIView的认证流程
微信截图_20190108211418
  • 解决方案2
DRF-基于APIView的认证流程
微信截图_20190108211524
  • 以后我们比如有些API需要认证才能看,我们就可以在这里进行操作

DRF认证流程:

  • 请求进来先走dispatch方法
  1. dispatch方法里面封装了request
DRF-基于APIView的认证流程
微信截图_20190108211939
  1. 调用initial
DRF-基于APIView的认证流程
微信截图_20190108212123
  1. 调用perform_authentication()


    DRF-基于APIView的认证流程
    微信截图_20190108212249
  2. 取user方法

DRF-基于APIView的认证流程
微信截图_20190108212402
  1. user方法里面调用了认证对象
DRF-基于APIView的认证流程
微信截图_20190108212533
  1. 遍历认证
DRF-基于APIView的认证流程
微信截图_20190108212748

使用

DRF-基于APIView的认证流程
微信截图_20190108213110
DRF-基于APIView的认证流程
微信截图_20190108213327
DRF-基于APIView的认证流程
微信截图_20190108213349
上一篇:Django-视图CBV执行流程详解


下一篇:DRF-访问频率配置(节流)