zoukankan      html  css  js  c++  java
  • drf 认证流程解析

    认证

    用于必须登录后才能访问否个视图。

    简单使用:

    url.py

    from django.conf.urls import url,include
    from django.contrib import admin
    from . import views
    urlpatterns = [
        url(r'^login/$', views.LoginView.as_view()),
        url(r'^order/$', views.OrderView.as_view()),
        url(r'^user/$', views.UserView.as_view()),
    ]
    
    

    views.py

    import uuid
    from django.shortcuts import render
    from django.views import View
    from django.views.decorators.csrf import csrf_exempt
    from django.utils.decorators import method_decorator
    from rest_framework.versioning import URLPathVersioning
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from . import models
    
    class LoginView(APIView):
    
        def post(self,request,*args,**kwargs):
            user_object = models.UserInfo.objects.filter(**request.data).first()
            if not user_object:
                return Response('登录失败')
            random_string = str(uuid.uuid4())	# 产生随机字符串
            user_object.token = random_string	#  保存在数据库
            user_object.save()
            return Response(random_string)
    
        
    class MyAuthentication:
        def authenticate(self, request):
            # 重写这个方法
            """
            Authenticate the request and return a two-tuple of (user, token).
            """
            token = request.query_params.get('token')
            # 获取请求携带的token,然后获取用户对象
            user_object = models.UserInfo.objects.filter(token=token).first()
            if user_object:
                return (user_object,token)
            return (None,None)
    
        
    class OrderView(APIView):
        authentication_classes = [MyAuthentication, ]
        # 需要登录认证的视图,设置类列表
        def get(self,request,*args,**kwargs):
            print(request.user)		# 获取用户对象
            print(request.auth)		# 获取token
            return Response('order')
    
    class UserView(APIView):
        authentication_classes = [MyAuthentication,]
        def get(self,request,*args,**kwargs):
            print(request.user)
            print(request.auth)
            return Response('user')
    

    源码:

    class APIView(View):
        authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
        
    	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.
            """
            # ###################### 第一步 ###########################
            """
            request,是django的request,它的内部有:request.GET/request.POST/request.method
            args,kwargs是在路由中匹配到的参数,如:
                url(r'^order/(d+)/(?P<version>w+)/$', views.OrderView.as_view()),
                http://www.xxx.com/order/1/v2/
            """
            self.args = args
            self.kwargs = kwargs
    
    
            """
            request = 生成了一个新的request对象,此对象的内部封装了一些值。
            request = Request(request)
                - 内部封装了 _request = 老的request
                - 内部封装了 authenticators = [MyAuthentication(), ] 对象类列表
            """
            request = self.initialize_request(request, *args, **kwargs)
            self.request = 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(), # 认证[MyAuthentication(),]
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
    
        
        def get_authenticators(self):
            """
            Instantiates and returns the list of authenticators that this view can use.
            """
            return [ auth() for auth in self.authentication_classes ]
        
    
    def perform_authentication(self, request):
    
        request.user
    

    会执行Request中def user()

    def user(self):
    	self._authenticate()
        
    def _authenticate(self):
        for authenticator in self.authenticators:
            user_auth_tuple = authenticator.authenticate(self)	# 循环上面获取到的认证对象类列表,执行自定制的auhenticate()方法
    

    流程分析:

    1. 当前请求到来时,执行APIview dispatch方法,request = self.initialize_request()先进行新的request封装,其中封装了老request、认证类对象列表等。 
    2. 然后执行 initial方法,先进行分页、再进行认证执行 perform_authentication()  --- request.user
    3.执行Request中def user(), user中循环认证类对象列表,执行每个对象的 def authenticate()(重写的方法),有三种返回方式:	 
        - 元组:认证通过
        - None:进行下个类的认证
        - 主动抛出异常:认证失败
    下面两种方式可以触发第三步的认证:
    	request.user 	能够获取当前登录用户对象
    	request.auth	获取toke
    
  • 相关阅读:
    virtualbox+vagrant学习-2(command cli)-19-vagrant box命令
    virtualbox+vagrant学习-2(command cli)-24-Aliases别名
    virtualbox+vagrant学习-2(command cli)-23-vagrant version命令
    virtualbox+vagrant学习-2(command cli)-22-vagrant validate命令
    如何快速学习一门技术或进入一个岗位
    EL表达式详解
    关于JSP乱码问题
    java mail使用qq邮箱发邮件的配置方法
    数据库命名规范
    java中的Serializable接口的作用
  • 原文地址:https://www.cnblogs.com/yzm1017/p/11953866.html
Copyright © 2011-2022 走看看