四、Drf认证组件

四、Drf认证组件

4.1 快速使用

python 复制代码
from django.shortcuts import render,HttpResponse
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

# Create your views here.
class Myauthentication(BaseAuthentication):
    """
    用户认证:
    1、读取请求传递过来的token
    2、校验合法性
    3、返回值
        --3.1返回元组,如(11,22),认证成功,request.user=11,request.auth=22
        --3.2抛出异常,认证失败,返回错误信息
        --3.3返回None,多个认证类[类1,类2,类3,类4..。。]-->匿名用户
    """
    def authenticate(self, request):
        #获取token
        token=request.GET.get('token')
        if token:
			#如果token校验成功,则返回一个元组(用户名和token),request.user=元组[0],request.auth=元组[1]
            return 'sally',token
        #如果校验失败则抛出异常
        raise AuthenticationFailed({'code':2000,'error':'认证失败'})

class LoginView(APIView):
    #该视图无需认证
    authentication_classes = []
    def get(self,request):
        #user和auth都为None
        print('user', request.user)
        print('auth', request.auth)
        return Response('login')

class UserView(APIView):
    #该视图要需认证
    authentication_classes = [Myauthentication,]
    def get(self, request):
        #user和auth为认证类Myauthentication返回的结果
        print('user',request.user)
        print('auth',request.auth)
        return Response('user')

class OrderView(APIView):
      #该视图要需认证
    authentication_classes = [Myauthentication, ]
    def get(self, request):
        #user和auth为认证类Myauthentication返回的结果
        print(request.user)
        print(request.auth)
        return Response('order')

认证的全局配置:

上个示例中,需要在每个视图中应用认证类,比较麻烦。

可以在settings.py中做全局配置

python 复制代码
REST_FRAMEWORK = {
    "UNAUTHENTICATED_USER": None,
    #这里指定一个或多个认证类(注意:认证类不能放在views合局视图文件中,不然会引发循环调用,这里将认证类放在了ext/auth文件中)
    "DEFAULT_AUTHENTICATION_CLASSES":["ext.auth.Myauthentication",]
}

这样,默认所有视图都需要认证,如果某些视图不需要认证,只需要在这些视图函数中加入'authentication_classes = []'即可。

python 复制代码
class LoginView(APIView):
    #不需要认证
    authentication_classes = []
    def get(self,request):
        print('user', request.user)
        print('auth', request.auth)
        return Response('login')

class UserView(APIView):
    # 需要认证
    def get(self, request):
        print('user',request.user)
        print('auth',request.auth)
        return Response('user')

class OrderView(APIView):
    # 需要认证
    def get(self, request):
        print(request.user)
        print(request.auth)
        return Response('order')

4.2多个认证类

python 复制代码
settings.py
REST_FRAMEWORK = {
    "UNAUTHENTICATED_USER": None,
    "DEFAULT_AUTHENTICATION_CLASSES":["ext.auth.Myauthentication1",
                                      "ext.auth.Myauthentication2",
                                      "ext.auth.Noauthentication",]
}
python 复制代码
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

class Myauthentication1(BaseAuthentication):  
    """
    用户认证:
    1、读取请求传递过来的token
    2、校验合法性
    3、返回值
        --3.1返回元组,如(11,22),认证成功,request.user=11,request.auth=22
        --3.2抛出异常,认证失败,返回错误信息
        --3.3返回None,多个认证类[类1,类2,类3,类4..。。]-->匿名用户
    """
    def authenticate(self, request):
        token=request.GET.get('token')

        if token=='123':
        	#如果验证成功,则返回用户名和token,不再执行下一个认证类
            print(token)
            return 'sally',token
        #如果验证失败,则返回None,如果返回None则会执行下一个认证类
        return None

class Myauthentication2(BaseAuthentication):
    """
    用户认证:
    1、读取请求传递过来的token
    2、校验合法性
    3、返回值
        --3.1返回元组,如(11,22),认证成功,request.user=11,request.auth=22
        --3.2抛出异常,认证失败,返回错误信息
        --3.3返回None,多个认证类[类1,类2,类3,类4..。。]-->匿名用户
    """

    def authenticate(self, request):
        token = request.GET.get('token')

        if token == '456':
        	#如果验证成功,则返回用户名和token,不再执行下一个认证类
            print(token)
            return 'ying',token
         #如果验证失败,则返回None,如果返回None则会执行下一个认证类
        return

class Noauthentication(BaseAuthentication):
    """
    用户认证:
    1、读取请求传递过来的token
    2、校验合法性
    3、返回值
        --3.1返回元组,如(11,22),认证成功,request.user=11,request.auth=22
        --3.2抛出异常,认证失败,返回错误信息
        --3.3返回None,多个认证类[类1,类2,类3,类4..。。]-->匿名用户
    """

    def authenticate(self, request):
        print('认证失败')
        #如果以上的认证类认证全部失败,则抛出错误,认证失败。
        raise AuthenticationFailed({'code':2000,'error':'认证失败'})

4.3认证状态码

python 复制代码
class Myauthentication1(BaseAuthentication):
 
    def authenticate(self, request):
        token=request.GET.get('token')

        if token=='123':
            print(token)
            return 'sally',token
        return None
    def authenticate_header(self, request):   
        #修改认证状态码
        return "API"

效果:

4.4子类约束
python 复制代码
class Foo(object):
    def f1(self):
        
    	#父类的函数中加上一个raise
        raise NotImplementedError
class New(Foo):
    def f2(self):
        #如果子类定义了一个父类中不存在的方法,则会报错
        print('f1')


obj=New()
复制代码
Traceback (most recent call last):
  File "G:\py_project\api\app_api\tests.py", line 70, in <module>
    obj.f1()
  File "G:\py_project\api\app_api\tests.py", line 61, in f1
    raise NotImplementedError
NotImplementedError

4.5示例:用户登入和查看用户信息

4.5.1创建用户表
python 复制代码
class User(models.Model):
    name=models.CharField(verbose_name='name',max_length=64)
    password=models.CharField(verbose_name='password',max_length=64)
    token=models.CharField(verbose_name='token',max_length=64,null=True,blank=True)
4.5.2用户登入
python 复制代码
class LoginView(APIView):
    #不需要认证
    authentication_classes = []
    def post(self,request):
        #获取用户通过POST方式传递过来的用户名和密码
        name=request.data.get('name')
        password=request.data.get('password')
        print(name,password)
        #尝试获取用户对象
        user_obj=models.User.objects.filter(name=name,password=password).first()
        if not user_obj:
            #如果用户对象不存在,代表用户名密码错误
            return Response({'status':False,'errMsg':'用户名或密码错误'})
        #为用户生成一个token并保存到数据库
        token=str(uuid.uuid4())
        user_obj.token=token
        user_obj.save()


        return Response({'status':True,'token':token})

使用postman发送POST请求

4.5.2查看用户信息
python 复制代码
# 视图类
class UserView(APIView):
    # 需要认证
    def get(self, request):
        #返回用户名和token
        return Response({'user':request.user.name,'token':request.auth})
python 复制代码
#settings.py
REST_FRAMEWORK = {
    "UNAUTHENTICATED_USER": None,
    #先认证URL参数中的token,如果认证失败则认证HTTP请求头部中的token,如果认证失败则进入未认证程序
    "DEFAULT_AUTHENTICATION_CLASSES":["ext.auth.Query_Params_authentication",
                                      "ext.auth.Header_authentication",
                                      "ext.auth.Noauthentication",]
}
python 复制代码
#ext.auth
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app_api import models
class Query_Params_authentication(BaseAuthentication):
    """
    url参数认证:
    1、读取请求url参数递过来的token
    2、校验合法性
    3、返回值
        认证通过,则返回用户对象和token,不会进入下一个认证类
        认证失败,返回None,进入下一个认证类
    """
    def authenticate(self, request):
        #从url参数中获取token
        token=request.query_params.get('token')
        if not token:
            # 如果token不存在,返回None,进行下个认证类
            return None
        user_obj=models.User.objects.filter(token=token).first()
        if user_obj:
            #如果用户存在,不在进行下个认证类
            return user_obj,token   #request.user=user_obj,request.auth=token
        #如果用户不存在,返回None,进行下个认证类
        return None

    def authenticate_header(self, request):
        return "API"

class Header_authentication(BaseAuthentication):
    """
    头部认证:
    1、读取HTTP请求头部传递过来的token
    2、校验合法性
    3、返回值
        认证通过,则返回用户对象和token,不会进入下一个认证类
        认证失败,返回None,进入下一个认证类
    """
    def authenticate(self, request):
        #从HTTP请求问部获取token
        token=request.META.get('HTTP_AUTHENTICATE')
        if not token:
            # 如果token不存在,返回None,进行下个认证类
            return None
        user_obj=models.User.objects.filter(token=token).first()
        if user_obj:
            #如果用户存在,不在进行下个认证类
            return user_obj,token   #request.user=user_obj,request.auth=token
        #如果用户不存在,返回None,进行下个认证类
        return None

    def authenticate_header(self, request):
        return "API"

class Noauthentication(BaseAuthentication):
    """
    未通过上面两次认证的,直接抛出错误:

    """

    def authenticate(self, request):
        #如果以上的认证类认证全部失败,则抛出错误,认证失败。
        raise AuthenticationFailed({'code':2000,'error':'认证失败'})

使用postman进行测试

1)url参数中传递token

2)HTTP头部传递token

3)token错误

相关推荐
知乎的哥廷根数学学派2 小时前
面向可信机械故障诊断的自适应置信度惩罚深度校准算法(Pytorch)
人工智能·pytorch·python·深度学习·算法·机器学习·矩阵
且去填词3 小时前
DeepSeek :基于 Schema 推理与自愈机制的智能 ETL
数据仓库·人工智能·python·语言模型·etl·schema·deepseek
人工干智能3 小时前
OpenAI Assistants API 中 client.beta.threads.messages.create方法,兼谈一星*和两星**解包
python·llm
databook3 小时前
当条形图遇上极坐标:径向与圆形条形图的视觉革命
python·数据分析·数据可视化
阿部多瑞 ABU3 小时前
`chenmo` —— 可编程元叙事引擎 V2.3+
linux·人工智能·python·ai写作
acanab4 小时前
VScode python插件
ide·vscode·python
知乎的哥廷根数学学派4 小时前
基于生成对抗U-Net混合架构的隧道衬砌缺陷地质雷达数据智能反演与成像方法(以模拟信号为例,Pytorch)
开发语言·人工智能·pytorch·python·深度学习·机器学习
WangYaolove13145 小时前
Python基于大数据的电影市场预测分析(源码+文档)
python·django·毕业设计·源码
知乎的哥廷根数学学派5 小时前
基于自适应多尺度小波核编码与注意力增强的脉冲神经网络机械故障诊断(Pytorch)
人工智能·pytorch·python·深度学习·神经网络·机器学习
cnxy1886 小时前
Python爬虫进阶:反爬虫策略与Selenium自动化完整指南
爬虫·python·selenium