DRF笔记二——认证

1、django请求周期

用户通过浏览器请求一个页面;

请求到达Request Middlewares中间件,中间件对request做一些预处理或者直接response请求;

URLConf通过urls.py文件和请求的URL找到相应的View;

View Middlewares被访问,它同样可以对request做一些处理或者直接返回response;

如果是FBV,直接调用View中的函数,如果是CBV,通过dispatch反射,执行对应method方法;

View中的方法可以选择性的通过Models访问底层的数据;

所有的Model-to-DB的交互都是通过manager完成的;

将数据通过HTTPResponse或者render发送到Response Middlewares中间件;

Response Middlewares中间件对View返回的response做一定处理;

返回到浏览器,呈现给用户;

2、认证

  • 问题1:有些api需要用户登录成功后才能访问;有些无需登录就能访问。

  • 基本使用认证组件

    解决:

    • 创建两张表(用户表,用户对应的token表)
    • 用户登录(返回token并保存到数据库)
  • 认证流程原理
    在这里插入图片描述

    如图所示:

    APIView类:

    ​ 1、先调用父类APIView中dispatch()方法;

    ​ 2、调用initialize_request()方法对request进行封装,封装后request为Request实例对象;

    ​ 3、调用initial(),去认证;

    ​ 4、调用perform_authentication()去实现认证;

    Request类:

    ​ 6、调用Request类中的user()方法;

    ​ 7、调用_authenticate()方法,获取认证对象,进行一步步认证

    ​ 8、在_authenticate()方法中循环所有认证对象,认证对象为authentication_classes = [],列表中的元素为一个个需要认证的实例化对象,在APIView中authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES,如果需要修改可在自己写的类中重写该类属性。

    ​ 9、执行认证类的authenticate方法,三种情况:

    • 如果authenticate()方法抛出异常,self._not_authenticated()执行

    • 如果有返回值,必须是元组:(request.user, request.auth)

    • 如果返回None,表示我不管,下一个认证来处理

      10、最后回到自定义的类中,执行相应的get或者post方法。

  • 全局配置

    1、全局使用的认证类,在setting.py文件配置

    REST_FRAMEWORK = {
        # 全局使用的认证类
        'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.auth.FirstAuthtication', 'api.utils.auth.Authtication'],
        }
    

    局部使用认证类,在需要认证的类中加入类属性:authentication_classes

    authentication_classes = [FirstAuthtication, Authtication, ]
    

    2、设置未认证成功后request.user与request.auth的值,在setting.py文件中设置

    REST_FRAMEWORK = {
        # 设置未认证成功后request.user与request.auth的值
        # 'UNAUTHENTICATED_USER': lambda: '匿名用户',  # request.user=匿名用户
        'UNAUTHENTICATED_USER': None,  # request.user=None
        'UNAUTHENTICATED_TOKEN': None  # request.auth=None
    }
    
  • 内置认证类

    1、认证类必须继承:BaseAuthentication,from rest_framework.authentication import BaseAuthentication

    2、其他认证类:BasicAuthentication,浏览器对用户名和密码进行base64加密,加密后放在请求头发送给服务端

    3、SessionAuthentication、TokenAuthentication、RemoteUserAuthentication都是基于django实现的。

  • 内容梳理

    1、使用

    • 创建类,继承BaseAuthentication;实现authenticate()方法

    • 返回值:

      None,下一个认证来执行;

      抛异常,raise exceptions.AuthenticationFailed(‘用户认证失败’),from rest_framework import exceptions;

      返回元组(元素1,元素2),元素1赋值给request.user,元素2赋值给request.auth;

    • 全局使用

      在配置文件里设置

      REST_FRAMEWORK = {
          # 全局使用的认证类,列表中是类的路径
          'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.auth.FirstAuthtication', 'api.utils.auth.Authtication'],
          # 'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.auth.FirstAuthtication'],
      
          # 设置未认证成功后request.user与request.auth的值
          # 'UNAUTHENTICATED_USER': lambda: '匿名用户',  # request.user=匿名用户
          'UNAUTHENTICATED_USER': None,  # request.user=None
          'UNAUTHENTICATED_TOKEN': None  # request.auth=None
      }
      
    • 局部使用

      在视图类中写个静态字段authentication_classes,列表中的元素是类的名称

      from rest_framework import exceptions
      from rest_framework.authentication import BaseAuthentication
      
      class Authtication(BaseAuthentication):
          def authenticate(self, request):
              token = request._request.GET.get('token')
              token_obj = models.UserToken.objects.filter(token=token).first()
              if not token_obj:
                  raise exceptions.AuthenticationFailed('用户认证失败')
              # 在rest framework内部会将两个字段赋值给request,以供后续操作使用
              # token_obj.user赋值给request.user,token_obj赋值给request.auth
              return (token_obj.user, token_obj)
      
          def authenticate_header(self, val):
              pass
          
      
      class OrderView(APIView):
          '''
          订单相关业务
          '''
          authentication_classes = [Authtication, ]
      
          def get(self, request, *args, **kwargs):
              ret = {
                  'code': 1000,
                  'msg': None,
                  'data': None
              }
              try:
                  ret['data'] = ORDER_DIC
              except Exception as e:
                  ret['code'] = 1002
                  ret['msg'] = '请求异常'
              return JsonResponse(ret)
      
  • 源码流程:

    • dispatch

      • 封装request

        获取定义的认证类(全局/局部),通过列表生成时创建对象。

      • initial

        perform_authentication

        request.user(内部循环认证对象…)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值