table of Contents
05 drf source code analysis of certification
1. Certification Brief
When we interact through a Web browser and API, we can log in, then the browser session will be requested to provide the necessary authentication.
If we interact with the API to programmatically, you need to explicitly provide authentication credentials on each request.
If we try to create a code segment without authenticating, you will receive an error message
2. Certification of Use
Creating a certification class MyAuthentication
class MyAuthentication(BaseAuthentication): def authenticate(self, request): """ Authenticate the request and return a two-tuple of (user, token). """ token = request.query_params.get('token') user_object = models.UserInfo.objects.filter(token=token).first() if user_object: return (user_object,token) return (None,None) # 最好继承Base类有一个约束
Add in the required certification class authentication_classes
class OrderView(APIView): authentication_classes = [MyAuthentication, ] def get(self,request,*args,**kwargs): print(request.user) print(request.auth) return Response('order') class UserView(APIView): authentication_classes = [MyAuthentication,] def get(self,request,*args,**kwargs): print(request.user) print(request.auth) return Response('user')
3. source code analysis
Dispatch request came first execution method
def dispatch(self, request, *args, **kwargs): """ - 内部封装了 authenticators = [MyAuthentication(), ] """ request = self.initialize_request(request, *args, **kwargs)
Initialize_request execution method, the authentication package to the new object list request object
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(), # [MyAuthentication(),] negotiator=self.get_content_negotiator(), parser_context=parser_context )
Get_authenticators execution method, the authentication class instantiated objects into the list of certification
def get_authenticators(self): return [ auth() for auth in self.authentication_classes ]
The method performs user authentication Request object
class Request: def __init__(self, request,authenticators=None): self._request = request self.authenticators = authenticators or () @property def user(self): if not hasattr(self, '_user'): with wrap_attributeerrors(): self._authenticate() return self._user
_authenticate approach uses the authenticate method of each certification class
def _authenticate(self): 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()
After successful authentication, the user object is assigned to request.user
@user.setter def user(self, value): self._user = value self._request.user = value
4. Summary
- When a user requests over dispatch performed, by initialize_request method,
- All the classes that are found and authenticated instantiated object list, the object list is then encapsulated into a new request object.
- The initial implementation of the following methods, certified request.user method
- List of objects circulating internally authentication and authenticate method performed for each object, the method for authentication, returns the value three, ① ② thrown returns a tuple returns None③
- Tuples returned values are assigned to two request.user and request.auth