前面的步骤都差不多,我们来看有差别的地方,我们说,request对象是APIView重写的,这个是在dispatch方法里面实现的,继续往后看dispatch方法,我们会看到self.initial方法,就是在这个方法里面,我们会看到认证、权限、频率几个组件的实现:

1.直接从APIView下面dispatch执行self.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)

2.执行self.perform_authentication(request),方法,注意,新的request对象被传递进去了

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

3.该方法只有一行request.user,根据之前的经验,解析器(request.data),我们知道这个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

4.所料不错,该方法继续执行self._authenticate(),注意此时的self是request对象

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()

 

5.该方法会循环self.authenticators,而这个变量是在重新实例化request对象时通过参数传递的

6.传递该参数是通过get_authenticatos()的返回值来确定的,它的返回值是

[ auth for auth in self.authentication_classes ]

  • 也就是我们的BookView里面定义的那个类变量,也就是认证类
  • 一切都明朗了,循环取到认证类,实例化,并且执行它的authenticate方法
    • 这就是为什么认证类里面需要有该方法
    • 如果没有该方法,认证的逻辑就没办法执行
    • 至于类里面的header方法,照着写就行,有兴趣的可以研究源码,这里就不细究了
  • 该方法如果执行成功就返回一个元组,执行完毕
    • 如果失败,它会捕捉一个APIException
    • 如果我们不希望认证通过,可以raise一个APIException

这就是认证组件的实现方式,非常简单。