目录
一、BaseAuthentication - 用于拦截请求,在视图函数钱执行相应认证方法
1-1 登陆相关视图函数 - 使用Token字符串存储数据库模拟session
1-2 BaseAuthentication 登陆认证 - drfAuth.py
二、认证配置 - authentication_classes
一、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
- import hashlib, time
- from app01 import models
- from django.core.exceptions import ObjectDoesNotExist
- from django.http import JsonResponse
- def get_token(name):
- '''
- 将当前时间戳转化为被hash的md5字符串
- - 注意:md5.update(内部必须插入bytes格式)
- :param name:
- :return:
- '''
- md5 = hashlib.md5()
- md5.update(str(time.time()).encode('utf-8'))
- md5.update(name.encode('utf-8'))
- return md5.hexdigest()
- class Login(APIView):
- '''
- 接收对应请求发送的数据,对其中的name和pwd进行校验
- - 校验通过:使用get_token(name)获取一个当前唯一的字符串作为token返回给前端,并且存入数据库中
- - 校验不通过:返回错误信息
- '''
- def post(self, request, *args, **kwargs):
- response = {'status': 100, 'msg': '登陆成功'}
- name = request.data.get('name')
- pwd = request.data.get('pwd')
- try:
- # 使用get获取表内符合对象,如不存在则报错
- user = models.UserInfo.objects.get(name=name, pwd=pwd)
- token = get_token(name)
- # update_or_create : 表内记录的更新或创建
- models.UserToken.objects.update_or_create(user=user, defaults={'token': token})
- response['token'] = token
- except ObjectDoesNotExist as e:
- response['status'] = 101
- response['msg'] = '用户名密码错误'
- except Exception as e:
- # 未知错误捕获
- response['status'] = 101
- response['msg'] = str(e)
- return JsonResponse(response, safe=False)
1-2 BaseAuthentication 登陆认证 - drfAuth.py
from rest_framework.authentication import BaseAuthentication
- from app01 import models
- from rest_framework import exceptions
- import datetime
- class LoginAuth(BaseAuthentication):
- # authenticate必须在DRF认证内被重写,request参数必须传入
- def authenticate(self, request):
- '''
- 将获取的token去token表内进行比对,存在信息即验证通过
- - 获取token表内token更新时间,若超时则验证失败重新登陆(用于数据的清理)
- - 验证通过:返回空 - 表示后续仍能继续其他验证
- = 验证通过:返回认证用户和当前数据记录对象 - 后续不再进行验证
- - 对应DRF内Request对象User类内_authenticate方法执行
- - from rest_framework.request import Request
- :param request:
- :return:
- '''
- # 数据放在header内传输,request.META获取
- # meta查询key值格式:HTTP_大写字段名 例如:token - HTTP_TOKEN
- token = request.META.get('HTTP_TOKEN')
- # token = request.query_params.get('token')
- print(token)
- ret = models.UserToken.objects.filter(token=token).first()
- if not ret:
- # 查不到,抛异常
- raise exceptions.APIException('认证失败,请重新登陆!')
- t = datetime.datetime.now() - ret.token_time
- print(t.total_seconds())
- # 若表内登陆时间超过10min则自动清除
- if t.total_seconds() > 600:
- ret.delete()
- raise exceptions.APIException('登陆超时,请重新登陆!')
- # 查询到对应用户信息,认证通过
- # 返回当前认证用户,当前token记录对象
- # 返回的数据可通过 request.user, request.auth进行获取
- return ret.user, ret
1-3 视图函数
from rest_framework.views import APIView
- from django.http import JsonResponse
- from app01 import MySerializer
- from app01 import drfAuth
- class Books(APIView):
- # 列表中,类名不能加括号
- authentication_classes = [drfAuth.LoginAuth, ]
- def get(self, request, *args, **kwargs):
- # 只要通过认证,就能取到当前登录用户对象
- print(request.user)
- response = {'status': 100, 'msg': '查询成功'}
- ret = models.Book.objects.all()
- book_ser = MySerializer.BookSerializer(ret, many=True)
- response['data'] = book_ser.data
- return JsonResponse(response, safe=False)
二、认证配置 - authentication_classes
2-1 局部配置
'''
- 需认证类内配置
- !! 注意:可以在列表中存入多个认证类,但是存在返回值的认证类必须位于最后!!
- '''
- authentication_classes = [drfAuth.LoginAuth, ]
2-2 全局配置 及 局部禁用
'''
- settings配置文件
- 所有视图内的类都会经过REST_FRAMEWORK内的认证类内认证
- '''
- REST_FRAMEWORK={
- 'DEFAULT_AUTHENTICATION_CLASSES':['app01.drfAuth.LoginAuth',]
- }
- '''
- 某一个视图类内禁用认证
- - 认证规则首先使用当前类内的 authentication_classes 规则
- - 置空表示不执行任何认证
- '''
- authentication_classes = []
标签:self,request,认证,token,user,import,BaseAuthentication From: https://www.cnblogs.com/clark1990/p/17152813.html三、相关源码分析
'''
- DRF内 Request对象 User类内 _authenticate方法
- '''
- def _authenticate(self):
- """
- Attempt to authenticate the request using each authentication instance
- in turn.
- """
- # 循环视图类内定义的所有认证类
- for authenticator in self.authenticators:
- try:
- # 执行当前认证类,并且获取返回值
- user_auth_tuple = authenticator.authenticate(self)
- # 若不存在返回值,抛出异常
- except exceptions.APIException:
- self._not_authenticated()
- raise
- # 若认证类存在返回值,并且符合self.user, self.auth返回规则,return跳出循环
- if user_auth_tuple is not None:
- self._authenticator = authenticator
- self.user, self.auth = user_auth_tuple
- return
- self._not_authenticated()