• django rest framework用户认证


    django rest framework用户认证


    • 进入rest framework的Apiview
      •  1 @classmethod
         2     def as_view(cls, **initkwargs):
         3         """
         4         Store the original class on the view function.
         5 
         6         This allows us to discover information about the view when we do URL
         7         reverse lookups.  Used for breadcrumb generation.
         8         """
         9         if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
        10             def force_evaluation():
        11                 raise RuntimeError(
        12                     'Do not evaluate the `.queryset` attribute directly, '
        13                     'as the result will be cached and reused between requests. '
        14                     'Use `.all()` or call `.get_queryset()` instead.'
        15                 )
        16             cls.queryset._fetch_all = force_evaluation
        17 
        18         view = super().as_view(**initkwargs)
        19         view.cls = cls
        20         view.initkwargs = initkwargs
        21 
        22         # Note: session based authentication is explicitly CSRF validated,
        23         # all other authentication is CSRF exempt.
        24         return csrf_exempt(view)

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


      •  1     def dispatch(self, request, *args, **kwargs):
         2         """
         3         `.dispatch()` is pretty much the same as Django's regular dispatch,
         4         but with extra hooks for startup, finalize, and exception handling.
         5         """
         6         self.args = args
         7         self.kwargs = kwargs
         8         request = self.initialize_request(request, *args, **kwargs)
         9         self.request = request
        10         self.headers = self.default_response_headers  # deprecate?
        11 
        12         try:
        13             self.initial(request, *args, **kwargs)
        14 
        15             # Get the appropriate handler method
        16             if request.method.lower() in self.http_method_names:
        17                 handler = getattr(self, request.method.lower(),
        18                                   self.http_method_not_allowed)
        19             else:
        20                 handler = self.http_method_not_allowed
        21 
        22             response = handler(request, *args, **kwargs)
        23 
        24         except Exception as exc:
        25             response = self.handle_exception(exc)
        26 
        27         self.response = self.finalize_response(request, response, *args, **kwargs)
        28         return self.response

        和django的dispatch类似,第8,9行对request进行了封装

      •  1     def initialize_request(self, request, *args, **kwargs):
         2         """
         3         Returns the initial request object.
         4         """
         5         parser_context = self.get_parser_context(request)
         6 
         7         return Request(
         8             request,
         9             parsers=self.get_parsers(),
        10             authenticators=self.get_authenticators(),
        11             negotiator=self.get_content_negotiator(),
        12             parser_context=parser_context
        13         )

        封装函数内部返回的是Request对象

      •  1 class Request:
         2     """
         3     Wrapper allowing to enhance a standard `HttpRequest` instance.
         4 
         5     Kwargs:
         6         - request(HttpRequest). The original request instance.
         7         - parsers_classes(list/tuple). The parsers to use for parsing the
         8           request content.
         9         - authentication_classes(list/tuple). The authentications used to try
        10           authenticating the request's user.
        11     """
        12 
        13     def __init__(self, request, parsers=None, authenticators=None,
        14                  negotiator=None, parser_context=None):
        15         assert isinstance(request, HttpRequest), (
        16             'The `request` argument must be an instance of '
        17             '`django.http.HttpRequest`, not `{}.{}`.'
        18             .format(request.__class__.__module__, request.__class__.__name__)
        19         )
        20 
        21         self._request = request
        22         self.parsers = parsers or ()
        23         self.authenticators = authenticators or ()
        24         self.negotiator = negotiator or self._default_negotiator()
        25         self.parser_context = parser_context
        26         self._data = Empty
        27         self._files = Empty
        28         self._full_data = Empty
        29         self._content_type = Empty
        30         self._stream = Empty
        31 
        32         if self.parser_context is None:
        33             self.parser_context = {}
        34         self.parser_context['request'] = self
        35         self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET
        36 
        37         force_user = getattr(request, '_force_auth_user', None)
        38         force_token = getattr(request, '_force_auth_token', None)
        39         if force_user is not None or force_token is not None:
        40             forced_auth = ForcedAuthentication(force_user, force_token)
        41             self.authenticators = (forced_auth,)

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

      • 查看self.authenticators
      • self.authenticators等于传进来的authenticators
      • 在ApiView内部定义了get_authenticators方法,它会被authenticators来接受
        1     def get_authenticators(self):
        2         """
        3         Instantiates and returns the list of authenticators that this view can use.
        4         """
        5         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捕捉

      • 效果
      •  

  • 相关阅读:
    14.6 将运算分组为事务
    Android 取得 ListView中每个Item项目的值
    【编程题目】n 个骰子的点数
    【编程题目】扑克牌的顺子
    【编程题目】颠倒栈☆
    【编程题目】输出 1 到最大的 N 位数
    【编程题目】寻找丑数
    【编程题目】在字符串中删除特定的字符
    【编程题目】复杂链表的复制☆
    【编程题目】找出数组中两个只出现一次的数字 ★★(自己没做出来)
  • 原文地址:https://www.cnblogs.com/ivy-blogs/p/11648778.html
Copyright © 2020-2023  润新知