django rest framework用户认证

django rest framework用户认证


  • 进入rest framework的Apiview
    •  @classmethod
      def as_view(cls, **initkwargs):
      """
      Store the original class on the view function. This allows us to discover information about the view when we do URL
      reverse lookups. Used for breadcrumb generation.
      """
      if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
      def force_evaluation():
      raise RuntimeError(
      'Do not evaluate the `.queryset` attribute directly, '
      'as the result will be cached and reused between requests. '
      'Use `.all()` or call `.get_queryset()` instead.'
      )
      cls.queryset._fetch_all = force_evaluation view = super().as_view(**initkwargs)
      view.cls = cls
      view.initkwargs = initkwargs # Note: session based authentication is explicitly CSRF validated,
      # all other authentication is CSRF exempt.
      return csrf_exempt(view)

      django的类视图是调用内部的as_view方法来实现CBV,在第18行调用了父类的as_view,父类的as_view调用了dispatch方法,这里在ApiView自定义了dispatch


    •      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 = 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

      和django的dispatch类似,第8,9行对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对象

    •  class Request:
      """
      Wrapper allowing to enhance a standard `HttpRequest` instance. Kwargs:
      - request(HttpRequest). The original request instance.
      - parsers_classes(list/tuple). The parsers to use for parsing the
      request content.
      - authentication_classes(list/tuple). The authentications used to try
      authenticating the request's user.
      """ def __init__(self, request, parsers=None, authenticators=None,
      negotiator=None, parser_context=None):
      assert isinstance(request, HttpRequest), (
      'The `request` argument must be an instance of '
      '`django.http.HttpRequest`, not `{}.{}`.'
      .format(request.__class__.__module__, request.__class__.__name__)
      ) self._request = request
      self.parsers = parsers or ()
      self.authenticators = authenticators or ()
      self.negotiator = negotiator or self._default_negotiator()
      self.parser_context = parser_context
      self._data = Empty
      self._files = Empty
      self._full_data = Empty
      self._content_type = Empty
      self._stream = Empty if self.parser_context is None:
      self.parser_context = {}
      self.parser_context['request'] = self
      self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET force_user = getattr(request, '_force_auth_user', None)
      force_token = getattr(request, '_force_auth_token', None)
      if force_user is not None or force_token is not None:
      forced_auth = ForcedAuthentication(force_user, force_token)
      self.authenticators = (forced_auth,)

      Request对象的初始化函数,它将原生django的request对象赋值给self._request,所以在ApiView视图中想使用原生的request要用request._request来使用

    • 查看self.authenticators
    • self.authenticators等于传进来的authenticators
    • 在ApiView内部定义了get_authenticators方法,它会被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]

      这个方法回去self.authentication_classes里面找定义好的对象再将其实例化

    • 定义自定义验证类
      from rest_framework.views import APIView
      from django.http import HttpResponse
      from rest_framework.authentication import BaseAuthentication
      from rest_framework.exceptions import AuthenticationFailed class MyAuthentication(BaseAuthentication):
      def authenticate(self, request):
      if not request._request.GET.get('name'):
      raise AuthenticationFailed
      return ('user', None) def authenticate_header(self, request):
      pass class MyView(APIView):
      authentication_classes = [MyAuthentication] def get(self, request):
         user = request.user
      return HttpResponse(user)

      验证类继承BaseAuthentication(不继承也可以,但都要实现authenticate)方法,在authenticate里面实现用户的认证,最后返回一个元祖,第一个元素为user对象,该对象被request.user接受, 第二个元素会被request.auth捕捉

    • 效果
    • django rest framework用户认证

      django rest framework用户认证

上一篇:CSS盒模型(Box Model)


下一篇:Django 中的用户认证