首页 > 其他分享 >BaseAuthentication

BaseAuthentication

时间:2023-02-24 19:13:06浏览次数:42  
标签:self request 认证 token user import BaseAuthentication

目录

一、BaseAuthentication - 用于拦截请求,在视图函数钱执行相应认证方法

1-1 登陆相关视图函数 - 使用Token字符串存储数据库模拟session

1-2 BaseAuthentication 登陆认证 - drfAuth.py

1-3 视图函数

二、认证配置 - authentication_classes

2-1 局部配置

2-2 全局配置 及 局部禁用

三、相关源码分析


一、BaseAuthentication - 用于拦截请求,在视图函数钱执行相应认证方法

总结:

  • 认证类
    • 认证类必须单独存放在py文件内,若防止在view内,使用全局配置时候,无法使用
    • 必须继承 BaseAuthentication
      • from rest_framework.authentication import BaseAuthentication
    • 认证类内必须重写 authenticate(self, request) 方法,request参数必须传入
    • 若后续有其他认证类需要执行,必须返回空!!
    • 若后续不无其他认证类需要执行,则返回两个值 - 对应DRF内Request对象User类内_authenticate方法执行
    • 认证失败,抛出  exceptions.APIException 异常 
      • from rest_framework import exceptions
  • 执行认证的视图类中配置 authentication_classes = [drfAuth.LoginAuth, ]

1-1 登陆相关视图函数 - 使用Token字符串存储数据库模拟session

  from rest_framework.views import APIView
  1. import hashlib, time
  2. from app01 import models
  3. from django.core.exceptions import ObjectDoesNotExist
  4. from django.http import JsonResponse
  5. def get_token(name):
  6. '''
  7. 将当前时间戳转化为被hash的md5字符串
  8. - 注意:md5.update(内部必须插入bytes格式)
  9. :param name:
  10. :return:
  11. '''
  12. md5 = hashlib.md5()
  13. md5.update(str(time.time()).encode('utf-8'))
  14. md5.update(name.encode('utf-8'))
  15. return md5.hexdigest()
  16. class Login(APIView):
  17. '''
  18. 接收对应请求发送的数据,对其中的name和pwd进行校验
  19. - 校验通过:使用get_token(name)获取一个当前唯一的字符串作为token返回给前端,并且存入数据库中
  20. - 校验不通过:返回错误信息
  21. '''
  22. def post(self, request, *args, **kwargs):
  23. response = {'status': 100, 'msg': '登陆成功'}
  24. name = request.data.get('name')
  25. pwd = request.data.get('pwd')
  26. try:
  27. # 使用get获取表内符合对象,如不存在则报错
  28. user = models.UserInfo.objects.get(name=name, pwd=pwd)
  29. token = get_token(name)
  30. # update_or_create : 表内记录的更新或创建
  31. models.UserToken.objects.update_or_create(user=user, defaults={'token': token})
  32. response['token'] = token
  33. except ObjectDoesNotExist as e:
  34. response['status'] = 101
  35. response['msg'] = '用户名密码错误'
  36. except Exception as e:
  37. # 未知错误捕获
  38. response['status'] = 101
  39. response['msg'] = str(e)
  40. return JsonResponse(response, safe=False)

1-2 BaseAuthentication 登陆认证 - drfAuth.py

  from rest_framework.authentication import BaseAuthentication
  1. from app01 import models
  2. from rest_framework import exceptions
  3. import datetime
  4. class LoginAuth(BaseAuthentication):
  5. # authenticate必须在DRF认证内被重写,request参数必须传入
  6. def authenticate(self, request):
  7. '''
  8. 将获取的token去token表内进行比对,存在信息即验证通过
  9. - 获取token表内token更新时间,若超时则验证失败重新登陆(用于数据的清理)
  10. - 验证通过:返回空 - 表示后续仍能继续其他验证
  11. = 验证通过:返回认证用户和当前数据记录对象 - 后续不再进行验证
  12. - 对应DRF内Request对象User类内_authenticate方法执行
  13. - from rest_framework.request import Request
  14. :param request:
  15. :return:
  16. '''
  17. # 数据放在header内传输,request.META获取
  18. # meta查询key值格式:HTTP_大写字段名 例如:token - HTTP_TOKEN
  19. token = request.META.get('HTTP_TOKEN')
  20. # token = request.query_params.get('token')
  21. print(token)
  22. ret = models.UserToken.objects.filter(token=token).first()
  23. if not ret:
  24. # 查不到,抛异常
  25. raise exceptions.APIException('认证失败,请重新登陆!')
  26. t = datetime.datetime.now() - ret.token_time
  27. print(t.total_seconds())
  28. # 若表内登陆时间超过10min则自动清除
  29. if t.total_seconds() > 600:
  30. ret.delete()
  31. raise exceptions.APIException('登陆超时,请重新登陆!')
  32. # 查询到对应用户信息,认证通过
  33. # 返回当前认证用户,当前token记录对象
  34. # 返回的数据可通过 request.user, request.auth进行获取
  35. return ret.user, ret

1-3 视图函数

  from rest_framework.views import APIView
  1. from django.http import JsonResponse
  2. from app01 import MySerializer
  3. from app01 import drfAuth
  4. class Books(APIView):
  5. # 列表中,类名不能加括号
  6. authentication_classes = [drfAuth.LoginAuth, ]
  7. def get(self, request, *args, **kwargs):
  8. # 只要通过认证,就能取到当前登录用户对象
  9. print(request.user)
  10. response = {'status': 100, 'msg': '查询成功'}
  11. ret = models.Book.objects.all()
  12. book_ser = MySerializer.BookSerializer(ret, many=True)
  13. response['data'] = book_ser.data
  14. return JsonResponse(response, safe=False)

二、认证配置 - authentication_classes

2-1 局部配置

  '''
  1. 需认证类内配置
  2. !! 注意:可以在列表中存入多个认证类,但是存在返回值的认证类必须位于最后!!
  3. '''
  4. authentication_classes = [drfAuth.LoginAuth, ]

2-2 全局配置 及 局部禁用

  '''
  1. settings配置文件
  2. 所有视图内的类都会经过REST_FRAMEWORK内的认证类内认证
  3. '''
  4. REST_FRAMEWORK={
  5. 'DEFAULT_AUTHENTICATION_CLASSES':['app01.drfAuth.LoginAuth',]
  6. }
  7. '''
  8. 某一个视图类内禁用认证
  9. - 认证规则首先使用当前类内的 authentication_classes 规则
  10. - 置空表示不执行任何认证
  11. '''
  12. authentication_classes = []

三、相关源码分析

  '''
  1. DRF内 Request对象 User类内 _authenticate方法
  2. '''
  3. def _authenticate(self):
  4. """
  5. Attempt to authenticate the request using each authentication instance
  6. in turn.
  7. """
  8. # 循环视图类内定义的所有认证类
  9. for authenticator in self.authenticators:
  10. try:
  11. # 执行当前认证类,并且获取返回值
  12. user_auth_tuple = authenticator.authenticate(self)
  13. # 若不存在返回值,抛出异常
  14. except exceptions.APIException:
  15. self._not_authenticated()
  16. raise
  17. # 若认证类存在返回值,并且符合self.user, self.auth返回规则,return跳出循环
  18. if user_auth_tuple is not None:
  19. self._authenticator = authenticator
  20. self.user, self.auth = user_auth_tuple
  21. return
  22. self._not_authenticated()

 

 

标签:self,request,认证,token,user,import,BaseAuthentication
From: https://www.cnblogs.com/clark1990/p/17152813.html

相关文章