在开发后端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"'
  1. 在认证类中将验证功能定义在authenticate函数中

  2. authenticate_header函数将返回值设置给响应头 WWW-Authenticate

  3. 对于验证失败,抛出AuthenticationFailed异常

  4. 验证成功,则返回一个元组,第一个元素为当前登录用户对象,第二个为验证token,封装在request中

    1. request.user

    2. Request.auth

  5. 跳过验证,返回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

  • 返回一个元组,一个用户,一个验证,终止验证,执行对应的视图函数

posted on 2022-11-14 20:58  阿明明  阅读(68)  评论(0编辑  收藏  举报