四、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错误

相关推荐
“AI国潮设计-小江”2 分钟前
《Python+SDXL实战:用ControlNet精准控制“英歌舞戚风蛋糕”质感,附批量生成脚本》
开发语言·人工智能·python·prompt·aigc
jayhgq9 分钟前
新一代Python包与项目管理工具——UV
开发语言·python·uv
for_ever_love__15 分钟前
文件与异常——open、json、with 与 try-except 的工程写法
python·异常处理·文件操作·大模型开发
XLYcmy16 分钟前
PDF 论文处理器 — 技术报告文档
数据库·python·网络安全·pdf·embedding·dify·rag
weixin_4404016918 分钟前
质朴的可视化绘图+pyecharts
开发语言·python·信息可视化·pyecharts
计算机毕业编程指导师22 分钟前
【Python毕设选题推荐】基于Spark的国内主要农作物产量趋势分析与可视化系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·python·数据分析·spark·毕业设计·课程设计·农作物产量
计算机毕业编程指导师28 分钟前
【Python毕设选题推荐】基于Spark的宫颈癌变光谱特征数据分析可视化系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·计算机·spark·毕业设计·宫颈癌变
ss27328 分钟前
AI全栈实战 | 3.3-01 Python OOP:__init__ 真的是构造函数吗,元类怎么让 Django Model 变魔法
开发语言·python·django
FYKJ_201030 分钟前
springboot心理健康管理系统86254-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·mysql·django·课程设计
海绵宝宝转agent9 小时前
learn-claude-code第1-5章开源学习笔记分享
人工智能·笔记·python·学习