前面的步骤都差不多,我们来看有差别的地方,我们说,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
这就是认证组件的实现方式,非常简单。