数据库准备
构造token
正式场景使用jwt构造token,而不是这里这种方式。
用户访问接口:服务器生成一个token,用于保存到数据库和返回给用户。
# models.pyfrom django.db import modelsclass UserInfo(models.Model):username = models.CharField(verbose_name="用户名", max_length=32)password = models.CharField(verbose_name="密码", max_length=64)token = models.CharField(verbose_name="TOKEN", max_length=64, null=True, blank=True)
# views.pyimport uuidfrom rest_framework.views import APIViewfrom rest_framework.response import Responsefrom rest_framework.authentication import BaseAuthenticationfrom rest_framework.exceptions import AuthenticationFailed# Create your views here.from app01 import modelsclass AuthView(APIView):'''提交的数据 {"username": "mufeng", "password": "123456"}'''def post(self, request, *args, **kwargs):print(request.data)username = request.data.get('username')password = request.data.get('password')user_object = models.UserInfo.objects.filter(username=username, password=password).first()if not user_object:return Response({'code': 1000, 'data': '用户名或密码错误'})token = str(uuid.uuid4())user_object.token = tokenuser_object.save()res = {'code': 0, 'data': {'token': token, 'name': username}}return Response(res)
访问接口
数据库的token字段成功保存。
认证类
在视图类中设置类变量 authentication_classes的值为 认证类 MyAuthentication,表示此视图在执行内部功能之前需要先经过认证。
认证类的内部就是去执行:authenticate方法,根据返回值来表示认证结果。
- 抛出异常AuthenticationFailed,表示认证失败。内部还会执行 
authenticate_header将返回值设置给响应头WWW-Authenticate 返回含有两个元素的元组,表示认证成功,并且会将元素的第1个元素赋值给
request.user、第2个值赋值给request.auth。第1个值,一般是用户对象。第2个值,一般是token
返回None,表示继续调用 后续的认证类 进行认证。 ```python from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed
class TokenAuthentication(BaseAuthentication): def authenticate(self, request): msg = {‘code’: 1002, ‘data’: ‘认证失败’} token = request.query_params.get(‘token’) if not token: raise AuthenticationFailed(msg)
user_object = models.UserInfo.objects.filter(token=token).first()if not user_object:raise AuthenticationFailed(msg)return user_object, token
```python# 使用认证类class OrderView(APIView):authentication_classes = [TokenAuthentication]def get(self, request, *args, **kwargs):return Response({'code': 1000, 'data': '认证成功'})
返回None
在视图类的
authentication_classes中定义认证类时,传入的是一个列表,支持定义多个认证类。当出现多个认证类时,drf内部会按照列表的顺序,逐一执行认证类的
authenticate方法,如果 返回元组 或 抛出异常 则会终止后续认证类的执行;如果返回None,则意味着继续执行后续的认证类。如果所有的认证类
authenticate都返回了None,则默认 request.user=”AnonymousUser” 和 request.auth=None,也可以通过修改配置文件来修改默认值。
REST_FRAMEWORK = {"UNAUTHENTICATED_USER": lambda: None,"UNAUTHENTICATED_TOKEN": lambda: None,}
”返回None“的应用场景:
当某个API,已认证 和 未认证 的用户都可以方法时,比如:
- 已认证用户,访问API返回该用户的视频播放记录列表。
 - 未认证用户,访问API返回最新的的视频列表。
 注意:不同于之前的案例,之前案例是:必须认证成功后才能访问,而此案例则是已认证和未认证均可访问。
多个认证类
一般情况下,编写一个认证类足矣。
当项目中可能存在多种认证方式时,就可以写多个认证类。例如,项目认证支持:
- 在请求中传递token进行验证。
 - 请求携带cookie进行验证。
 - 请求携带jwt进行验证(后面讲述)。
 - 请求携带的加密的数据,需用特定算法解密(一般为app开发的接口都是有加密算法)
 - …
 
此时,就可以编写多个认证类,并按照需要应用在相应的视图中,例如:
全局配置
在每个视图类的类变量 authentication_classes 中可以定义,其实在配置文件中也可以进行全局配置,例如
REST_FRAMEWORK = {"UNAUTHENTICATED_USER": lambda: None,"UNAUTHENTICATED_TOKEN": lambda: None,"DEFAULT_AUTHENTICATION_CLASSES":["xxxx.xxxx.xx.类名","xxxx.xxxx.xx.类名",]}
底层源码实现


