首页 > 编程语言 >认证组件及源码分析

认证组件及源码分析

时间:2024-04-21 22:16:16浏览次数:15  
标签:authenticate self request auth 认证 authentication 源码 user 组件

认证组件

​ 用于判断用户是否登录

简单使用

# 1.创建一个任意名字的py文件

# 2.导入认证类
from rest_framework.authentication import BaseAuthentication

# 3.写一个类继承它并且重写authenticate方法
class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        token = request.META.get('HTTP_TOKEN')
        user_token = models.User_token.objects.filter(token=token).first()
        if user_token:
            return user_token.user, token
        else:
            raise AuthenticationFailed('请先登录')

# 4.在views.py导入这个自己写的类
from .authentication import LoginAuth

# 5.局部使用 在视图类下写authentication_classes属性,并且将自己写的认证类加到这个列表
class UserOperation():
    authentication_classes = [LoginAuth]
    
# 6.全局使用 在settings.py文件下配置REST_FRAMEWORK 
	REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES':[
        'app01.auth.Login_authentication'
    ]
}
    
# 7.局部禁用 在某个想要禁用的视图类下定义列表为空
authentication_classes = []

认证类源码解析

​ 在视图类执行as_view()时会先到dispath()封装一个新的request

dispatch

def dispatch(self, request, *args, **kwargs):
    self.args = args
    self.kwargs = kwargs
    # 通过initialize_request封装新的request 
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?

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
    )

get_authenticators

def get_authenticators(self):
    # 会通过遍历这个authentication_classes可迭代对象来以此调用里面的认证类对象
    # 这就是为什么我们需要在视图类里面定义这么一个列表或者元组
    return [auth() for auth in self.authentication_classes]

回到dispatch方法里面,查看三大认证操作

initial

def initial(self, request, *args, **kwargs):
	# 这三行代码进行了三大认证,点到perform_authentication里面看一看
    self.perform_authentication(request)
    self.check_permissions(request)
    self.check_throttles(request)

perform_authentication

def perform_authentication(self, request):
	# 就这么一行代码 看不出什么
    # 要想知道user是什么 从哪里来,就要去看看这个request的类是这么定义的
    # 当前这个request是经过Request包装过的新的request
    # 所以接下来去看看Request()这个类
    request.user

Request

发现user是一个包装成属性的方法

@property
def user(self):
    # 如果当前request没有_user这个属性,就执行_authenticate方法
    if not hasattr(self, '_user'):
        # 做了一个异常捕获
        with wrap_attributeerrors():
            self._authenticate()
    # 最后是返回了一个_user 说明_authenticate一定对_user赋值了
    return self._user

# 所以接下来点到_authenticate方法看一看

_authenticate方法

def _authenticate(self):
    # authenticators是实例化request对象时传入的参数,
    # 他是一个列表,列表里面是一个个认证类的实例
    for authenticator in self.authenticators:
        try:
            # 如果没有东西就会被异常捕获
            user_auth_tuple = authenticator.authenticate(self)
        except exceptions.APIException:
            self._not_authenticated()
            raise
		
        # 如果user_auth_tuple非空,就说明认证类里面的authenticate方法返回东西了
        if user_auth_tuple is not None:
            # 把认证类实例赋值给_authenticator
            self._authenticator = authenticator
            # 分别把值赋给user和auth
            # 也就是此时 request.user 就有值了
            self.user, self.auth = user_auth_tuple
            return
	
    # 如果没有报错,且没有返回元组,那么就执行了这么个玩意
    self._not_authenticated()
    
# 下面点进_not_authenticated

_not_authenticated

def _not_authenticated(self):
    self._authenticator = None
	# 如果配置文件配置了这个对象
    if api_settings.UNAUTHENTICATED_USER:
        # 就会执行某个函数,然后把返回值赋给user
        # 这个函数点进去看就会发现时执行了__str__方法然后返回了个字符串AnonymousUser
        # 也就是匿名用户的意思
        self.user = api_settings.UNAUTHENTICATED_USER()
    else:
        self.user = None

    if api_settings.UNAUTHENTICATED_TOKEN:
        self.auth = api_settings.UNAUTHENTICATED_TOKEN()
    else:
        self.auth = None

手动设置user

@user.setter
def user(self, value):
	# 这段源码解释了
    # 当手动设置user对象的时候
    # 还会把老的request.user 也设置成当前设置的user对象
    self._user = value
    self._request.user = value

总结

​ 当请求来的时候会执行dispach方法initialize_request方法包装新的request对象

​ Request会传入authenticators=self.get_authenticators(),如果你定义了序列化类,就会实例化这个类,把这个对象加到一个列表里,如果没有就不会触发校验

​ 这时候新的request对象已经生成好了,然后视图类对象会执行initial方法,这里面会触发perform_authentication方法进行认证,

​ 这个方法会执行request.user,然后执行Request类的_authenticate方法,这里就会根据你的序列化类的authenticate方法的返回值给request.user和request.auth赋值。

标签:authenticate,self,request,auth,认证,authentication,源码,user,组件
From: https://www.cnblogs.com/Hqqqq/p/18149592

相关文章

  • 权限组件及源码分析
    权限组件​ 通过观察APIView的源码,会发现他的里面执行了三个方法self.perform_authentication(request)#认证self.check_permissions(request)#权限self.check_throttles(request)#频率​ 也由此看出,权限是在认证之后执行的权限类的编写写一个类,继承Base......
  • 频率组件及源码分析
    频率组件​ 他的作用是限制接口访问的频率频率类的编写写一个类,继承SimpleRateThrottle重写get_cache_key,返回唯一标识,返回什么就以什么做限制重写类属性rate控制频率fromrest_framework.throttlingimportBaseThrottle,SimpleRateThrottleclassCommonThrottling(S......
  • DRF之路由组件
    一、路由的写法1、原始写法(1)介绍是指手动编写路由规则的方式。使用path()函数或re_path()函数来定义路由规则,并将其与对应的视图函数或类关联起来。(2)示例假设有一个名为book的应用,它包含了一个处理图书列表的视图函数book_list,以及一个处理单个图书详情的视图函数book_de......
  • 全局异常捕获及源码分析
    全局异常捕获​ drf只会捕获属于drf的异常,所以要做到全局异常捕获,还需要手动操作一下。​ 经过对drf异常处理组件的源码分析之后可以得知,其实就是自己定义一个exception_handler函数,然后全局替换一下即可​ 首先要知道,虽然是自己写一个exception_handler函数,但是drf的exception......
  • 分页组件
    分页组件​ 查询所有,才有分页功能(例如网站的下一页功能,app下挂加载更多)PageNumberPagination基本分页重要类属性page_size=api_settings.PAGE_SIZE(每页显示条数)page_query_param='page'(查询时用的参数)page_size_query_param=None(更改返回条数)max_page_size=......
  • 视图组件
    两个视图基类APIView#APIView是rest-framwork提供的所有视图类的基类,它继承自django的View类#在APIView中仍然以常规的类视图定义方法来实现get()、post()...请求方式的方法APIView和View的区别传入到视图方法中的请求对象是rest-framwork的Reqeust类的对象,而不是djang......
  • 路由组件
    Routers​ 对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系,还可以使用Routers类来快速实现路由的创建SimpleRouter(常用)DefaultRouter(用的少)#方式一#1.导入Routers类fromrest_framework.routersimportDefaultRouter#2.实例化对......
  • Django之settings源码分析
    引入查看源码的前提刚开始阅读一些库的源码的时候,最好选一些代码量少的先感受一下看到看不懂的,没有必要去死磕,挑一些看得懂的,再结合网上的一些文献一.django的两个配置文件一个是暴露给用户可以自己自定义的配置文件也就是项目根目录下的settings.py一个是项目默认的配......
  • 在React中的函数组件和类组件——附带示例的对比
    在React中,创建组件有两种主要方式:函数组件和类组件。每种方式都有自己的语法和用例,尽管随着ReactHooks的引入,它们之间的差距已经显著缩小。但选择适当的组件类型对于构建高效和可维护的React应用程序仍然非常关键。在本文中,我们将探讨函数和类组件之间的基本区别,清楚地理解它们......
  • 计算机毕业设计源码-基于 SpringBoot 开发的班级综合测评系统研究与实现
    技术栈开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9浏览器:谷歌浏览器3.需求分析用户需求分析根据账号登陆进入班级综合测评管理系统,系统根据角色展示相应......