在开发后端API的时候,不同的功能可能有不同的限制,如
-
无需验证:API可以直接访问
-
需要验证:API只有用户通过验证才可以访问
这个时候我们就可以使用DRF提供的认证组件,下面通过一个例子介绍
我们希望用户在登录之后,才能访问订单页面
模型类
from django.db import models class 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)
用户登录类
""" 根据前端传递过来的用户名和密码,生成对应的token,返回给前端 """ class AuthView(APIView): """ 用户登录验证 """ def post(self, request, *args, **kwargs): username = request.data.get('username') password = request.data.get('password') user_object = UserInfo.objects.filter(username=username, password=password).first() if not user_object: return Response( { 'code': 1000, 'data': '用户名或者密码错误' } ) token = str(uuid.uuid4()) user_object.token = token user_object.save() return Response({ 'code': 0, 'data': {'token': token, 'name': username} })
认证类
from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed class MyAuthentication(BaseAuthentication): def authenticate(self, request): token = request.query_params.get('token') if not token: raise AuthenticationFailed({ 'code': 1000, 'data': '验证失败', }) user_object = UserInfo.objects.filter(token=token).first() if not user_object: raise AuthenticationFailed({ 'code': 1000, 'data': '验证失败', }) return user_object, token def authenticate_header(self, request): return 'Bearer realm="API"'
-
在认证类中将验证功能定义在
authenticate
函数中 -
authenticate_header函数将返回值设置给响应头
WWW-Authenticate
-
对于验证失败,抛出
AuthenticationFailed
异常 -
验证成功,则返回一个元组,第一个元素为当前登录用户对象,第二个为验证token,封装在request中
-
request.user
-
Request.auth
-
-
跳过验证,返回None
订单视图类
class OrderView(APIView): authentication_classes = [MyAuthentication, ] def get(self, request, *args, **kwargs): print(request.user) print(request.auth) return Response({ 'code': 0, 'data': '订单数据' })
在视图类中设置类变量 authentication_classes的值为 认证类 MyAuthentication,表示此视图在执行内部功能之前需要先经过 认证。 认证类是可以使用多个的,从上面中列表就可以知道,一般情况下一个认证类就够了。但有时候我们需要支持多种验证方式 在请求中使用token 进行cookie验证 ...
关于返回None
-
在视图类的
authentication_classes
中定义认证类时,传入的是一个列表,支持定义多个认证类。 -
当出现多个认证类时,drf内部会按照列表的顺序,逐一执行认证类的
authenticate
方法,如果 返回元组 或 抛出异常 则会终止后续认证类的执行;如果返回None,则意味着继续执行后续的认证类。 -
如果所有的认证类
authenticate
都返回了None,则默认 request.user="AnonymousUser" 和 request.auth=None,也可以通过修改配置文件来修改默认值
全局配置
REST_FRAMEWORK = { "UNAUTHENTICATED_USER": lambda: None, "UNAUTHENTICATED_TOKEN": lambda: None, "DEFAULT_AUTHENTICATION_CLASSES":["xxxx.xxxx.xx.类名","xxxx.xxxx.xx.类名",] }
底层源码实现
关于authenticate返回值小结
-
抛出异常,则终止验证,返回可前端错误数据
-
返回None,跳过该验证类,执行下一个验证类的authenticate
-
返回一个元组,一个用户,一个验证,终止验证,执行对应的视图函数