认证组件

认证组件

认证组件实现步骤

  • 第一步:写一个类继承BaseAuthentication,重写authenticate方法(写认证逻辑)

  • 第二步:全局与局部使用认证组件设置

    # 全局
    REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES": ["app01.app_auth.MyAuthentication", ]
    }
    
    # 局部
    authentication_classes = [认证类1, 认证类2...]
    

认证组件源码

组件位置:APIView——>dispatch方法——>self.initial(request, *args, **kwargs)——>里面有三大组件(认证、权限、频率)

认证组件:self.perform_authentication(request)中就一句话:request.user——>调了rest_framework的Request类中的user方法属性

# 组件位置
def initial(self, request, *args, **kwargs):
    self.perform_authentication(request) # 认证
    self.check_permissions(request) # 权限
    self.check_throttles(request) # 频率
# 认证组件
def perform_authentication(self, request):
    request.user
    
# drf的Request类
@property
def user(self):
    if not hasattr(self, '_user'):
        with wrap_attributeerrors():
            self._authenticate()
    return self._user

Request类中的user方法,刚开始并没有_user,所以走 _authenticate()

认证组件的核心就是Request类的 _authenticate()

    def _authenticate(self):
        # 遍历拿到一个个认证器,进行认证
        # self.authenticators配置的一堆认证类产生的认证类对象组成的 list
        #self.authenticators 你在视图类中配置的一个个的认证类:authentication_classes=[认证类1,认证类2],对象的列表
        for authenticator in self.authenticators:
            try:
                # 认证器(对象)调用认证方法authenticate(认证类对象self, request请求对象)
                # 返回值:登陆的用户与认证的信息组成的 tuple
                # 该方法被try包裹,代表该方法会抛异常,抛异常就代表认证失败
                user_auth_tuple = authenticator.authenticate(self) #注意这self是request对象
            except exceptions.APIException:
                self._not_authenticated()
                raise

            # 返回值的处理
            if user_auth_tuple is not None:
                self._authenticator = authenticator
                # 如何有返回值,就将 登陆用户 与 登陆认证 分别保存到 request.user、request.auth
                self.user, self.auth = user_auth_tuple
                """
                一旦认证中返回两个值,此处得for循环直接结束,后续得认证都不会执行
                多个认证时,一定要把返回两个值写在最后面
                返回两个值,第一个是user对象,第二个是token(也可以是其他任意东西)
                """
                return
        # 如果返回值user_auth_tuple为空,代表认证通过,但是没有 登陆用户 与 登陆认证信息,代表游客
        self._not_authenticated()

认证组件的使用

认证类的使用

# auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from drf_day04.models import UserToken

class UserAuth(BaseAuthentication):
    # 重写父类的authenticate方法,返回两个值,或者抛出AuthenticationFailed异常
    def authenticate(self, request):
        token = request.query_params.get('token')
        if token:
            user_token = UserToken.objects.filter(token=token).first()
            if user_token:
                return user_token.user, token
            else:
                raise AuthenticationFailed('认证失效,请重新登录')
        else:
            raise AuthenticationFailed('请先登录')

局部与全局配置

# 全局配置:在settings.py中配置
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.app_auth.MyAuthentication", ]
}

# 局部配置:在视图类中添加authentication_classes = [认证类1, 认证类2...]
authentication_classes = [UserAuth]

# 局部禁用:在视图类中添加authentication_classes = []空列表
authentication_classes = []
posted @ 2020-07-09 18:49  群青-Xi  阅读(111)  评论(0编辑  收藏  举报