• rest_framework认证流程


    安装

    pip3 install djangorestframework

    使用

    基于cbv使用rest_framework框架

    from rest_framework.views import APIView  # rest_framework框架,继承View
    class ApiTest(APIView):
        pass

    当用户请求进来,执行父类的as_view方法, 返回view函数,执行dispatch方法,由于继承了APIView,会执行此类下边的dispatch方法

    def dispatch(self, request, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        # 这里用initalize_request方法对原生的request进行加工
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
        try:
            # 对加工之后的request处理,看下这里边的逻辑
            self.initial(request, *args, **kwargs)
            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

    可以看到,APIView类下的dispatch方法相比于View中的dispatch方法,除了反射请求还多了一些操作

    比如,对本来的request用initialize_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类生成了一个新的对象,新的对象包含了原有的request属性,还有一些其他的属性,

    这里看下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点开之后是读取的rest_frame的配置文件

    class APIView(View):
        # The following policies may be set at either globally, or per-view.
        renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
        parser_classes = api_settings.DEFAULT_PARSER_CLASSES
        authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES #这里
        throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
        permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
        content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
        metadata_class = api_settings.DEFAULT_METADATA_CLASS
        versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

    如果我们在我们自己的类里边写入authentication_classes参数,就可以读取我们自己设置的,不用APIView下边的

    from rest_framework.authentication import BasicAuthentication
    class ApiTest(APIView):
        authentication_classes = [BasicAuthentication] 

    到这里,我们已经大概知道dispatch对request进行了一些封装,接下来看下边的代码

    def dispatch(self, request, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        # 这里用initalize_request方法对原生的request进行加工
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request  # 赋值
        self.headers = self.default_response_headers  # deprecate?
    ------------------------------------------------------------------------------------------- try: # 对加工之后的request处理,看下这里边的逻辑 self.initial(request, *args, **kwargs) 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

     try下边的initial方法,把封装了数据之后的request当参数,我们点开这个方法

        def initial(self, request, *args, **kwargs):
            """
            Runs anything that needs to occur prior to calling the method handler.
            """
            self.format_kwarg = self.get_format_suffix(**kwargs)
    
    ......
    self.perform_authentication(request) # 封装过数据之后的request,认证用 self.check_permissions(request) self.check_throttles(request)

    发现有一个perform_authentication方法,点开这个方法里边执行了user属性方法

    @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

    authenticate

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

    修改authentacate方法,实现验证功能

    from django.shortcuts import HttpResponse
    import json
    
    from rest_framework.views import APIView  # rest_framework框架,继承View
    from rest_framework.authentication import BasicAuthentication
    from rest_framework import exceptions  # 验证失败触发异常
    
    
    class Myauthentication(object):
        def authenticate(self, request):
            username = request._request.GET.get("username")  # 验证成功返回元组
            if not username:
                raise exceptions.AuthenticationFailed("用户名未登录")  # 无返回验证失败,触发异常
            return ("status",1)
    
        def authenticate_header(self, val):
            pass
    
    
    class ApiTest(APIView):
        authentication_classes = [Myauthentication]  # 通过自定义的类做认证
    
        def get(self, request, *args, **kwargs):  # 用于处理get请求
            print(request)
            res = {
                "code": 1000,
                "msg": "hello world"
            }
            return HttpResponse(json.dumps(res))
    
        def post(self, request, *args, **kwargs):
            return HttpResponse("post")
    
        def put(self, request, *args, **kwargs):
            return HttpResponse("put")
    
        def delete(self, request, *args, **kwargs):
            return HttpResponse("delete")
  • 相关阅读:
    区间DP入门
    Prime Permutation(思维好题 )
    小字辈 (bfs好题)
    博弈论小结之尼姆博弈
    Hometask
    Lucky Sum (dfs打表)
    对称博弈
    尼姆博弈
    莫队算法 ( MO's algorithm )
    Codeforces 988D Points and Powers of Two ( 思维 || 二的幂特点 )
  • 原文地址:https://www.cnblogs.com/ligiao/p/11493814.html
Copyright © 2020-2023  润新知