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

相关推荐
长和信泰光伏储能6 小时前
京津冀光伏发电:绿色能源的未来之路
python·能源
浦信仿真大讲堂6 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
Gu Gu Study6 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
卷无止境7 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境7 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd1237 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy12393102168 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb008 小时前
一个项目带你入门AI应用开发01
python
0566469 小时前
Python康复训练——常用标准库
开发语言·python·学习
昆曲之源_娄江河畔9 小时前
Python如何安装flask, pymssql
开发语言·python·flask·pymssql