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

相关推荐
星越华夏1 小时前
python中四种获取文件后缀名的方法
开发语言·python
lunzi_08261 小时前
【学习笔记】《Python编程 从入门到实践》第9章:类、继承、组合与面向对象编程
笔记·python·学习
大蚂蚁2号1 小时前
本地批量音视频转文本免费工具
python·音视频·开源软件
copyer_xyf1 小时前
FastAPI 项目骨架搭建
前端·后端·python
十正1 小时前
aiohttp.TCPConnector 连接池原理详解
网络·python·tcp·aiohttp
LoserChaser1 小时前
Flask 文件上传服务器 - 知识点总结
服务器·python·flask
cd988801 小时前
2026年,哪家电销机器人定制更灵活?
python
二十七剑1 小时前
LangGraph 源码深度解析:_branch.py 条件分支底层实现原理
python
KaMeidebaby1 小时前
卡梅德生物技术快报|噬菌体展示文库构建全流程解析 | 大豆球蛋白纳米抗体筛选实践
人工智能·python·tcp/ip·算法·机器学习
傻啦嘿哟1 小时前
为什么Python没有块级作用域?
开发语言·python