> 文章列表 > Django REST Framework(DRF)框架之认证Authentication与权限Permission

Django REST Framework(DRF)框架之认证Authentication与权限Permission

Django REST Framework(DRF)框架之认证Authentication与权限Permission

DRF框架之认证与权限

  • 认证与权限
    • 认证(Authentication)
    • 权限(Permission)
  • 认证和权限的使用
    • 创建用户用于验证
    • 配置认证与权限(全局)
    • 视图指定认证与权限(局部)
  • 自定义权限
    • 概述
    • 创建自定义权限类
    • 使用自定义权限类
  • 使用TokenAuthentication身份验证
    • 配置
    • 执行数据库迁移
    • 创建一个认证令牌
    • 创建视图
    • 测试

认证与权限

Django REST Framework (DRF)提供了一系列的认证与权限功能来保护Web API不被未授权用户访问或滥用。

认证(Authentication)

在DRF中,认证是指验证用户身份的过程,如果用户提供的凭据(例如用户名和密码)通过验证,则认为该用户是经过认证的用户。

DRF支持多种认证方式:

SessionAuthentication: 基于django的session机制实现的认证方式,在使用时需要先登录获取session id,然后发送请求时携带该session idBasicAuthentication: 基于HTTP Basic Authentication协议实现的认证方式,用户需要在请求头中携带base64编码后的用户名和密码TokenAuthentication: 基于Token的认证方式,用户需要先通过用户名和密码获取一个Token,然后在每次请求时携带该Token进行认证JSONWebTokenAuthentication: 基于JSON Web Token(JWT)的认证方式,具有无状态、可扩展性等优点

DRF框架默认在rest_framework.settings文件中进行了全局认证方案的设置

DEFAULTS = {'DEFAULT_AUTHENTICATION_CLASSES': (# sesssion认证'rest_framework.authentication.SessionAuthentication', # 基本认证'rest_framework.authentication.BasicAuthentication' )
}

Django REST Framework(DRF)框架之认证Authentication与权限Permission

权限(Permission)

在DRF中,权限是指控制用户对API资源访问的能力。权限控制可以限制用户对于视图API的访问和对于具体数据对象的访问。

1.在执行视图的dispatch()方法前,会先进行视图访问权限的判断2.在通过get_object()获取具体对象时,会进行对象访问权限的判断

DRF提供了多种预设的权限类:

IsAuthenticated: 仅允许已经认证的用户访问AllowAny: 允许任何人访问IsAdminUser: 仅允许管理员用户访问IsAuthenticatedOrReadOnly: 对于未认证的用户只允许进行读取操作,已认证用户可以执行任意操作DjangoModelPermissions: 基于Django模型的权限控制,与Django admin中的权限控制类似DjangoObjectPermissions: 基于Django模型对象的权限控制

也可以自定义权限类,实现更加灵活的权限控制。

DRF框架默认在rest_framework.settings文件中进行了全局权限控制方案的设置

DEFAULTS = {'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny', # 允许所有人)
}

认证和权限的使用

创建用户用于验证

使用Django自带用户认证系统,创建一个用户,用于登录验证

import osfrom django.test import TestCasefrom django.contrib.auth.models import User
if not os.environ.get('DJANGO_SETTINGS_MODULE'):os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'meiduo_mall.settings')import django
django.setup()class MyTest(TestCase):User.objects.create_user(username='admin', password='admin')

配置认证与权限(全局)

可以在DRF项目的settings.py文件中修改DRF框架的全局认证方案与全局权限控制方案

REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': (# 基本认证'rest_framework.authentication.BasicAuthentication',# sesssion认证'rest_framework.authentication.SessionAuthentication',),'DEFAULT_PERMISSION_CLASSES': (# 将全局权限控制方案设置为仅允许认证用户访问'rest_framework.permissions.IsAuthenticated',)
}

认证与权限控制配置好后,访问某URL将出现BasicAuthentication认证框。

Django REST Framework(DRF)框架之认证Authentication与权限Permission
认证成功:
Django REST Framework(DRF)框架之认证Authentication与权限Permission
认证失败:
Django REST Framework(DRF)框架之认证Authentication与权限Permission

视图指定认证与权限(局部)

可以在每个视图中通过设置authentication_classess属性与permission_classes 属性设置视图的认证与权限方案

from rest_framework.authentication import SessionAuthentication, BasicAuthenticationclass TestView(ModelViewSet):queryset = User.objects.all()serializer_class = UserSerializer# 指定当前视图的认证方案,不使用全局认证方案authentication_classess = [BasicAuthentication, SessionAuthentication]# 指定当前视图的权限控制方案,不使用全局权限控制方案permission_classes = [IsAuthenticated]

配合权限,如果认证失败会有两种可能的返回值:

401 Unauthorized 未认证403 Permission Denied 权限被禁止

自定义权限

概述

自定义权限控制类,需继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部方法。

.has_permission(self, request, view) :

判断对使用此权限类的视图是否有访问权限, request表示请求对象,view表示当前视图对象,必须返回一个布尔值,指示请求是否被允许。

.has_object_permission(self, request, view, obj):

判断使用此权限类视图某个数据对象是否有访问权限, request表示请求, view表示当前视图, obj为数据对象

两者区别:

如果要在全局范围内控制某些操作,则使用has_permission()方法。如果要在单个对象级别控制某些操作,则使用has_object_permission()方法。

注意:

如果请求被授予访问权限,方法应该返回True,否则返回False。仅当视图级has_permission检查已通过时,才会调用实例级has_object_permission方法。

创建自定义权限类

创建一个名为MyPermission的自定义权限类。该类继承DRF的BasePermission,并覆盖了其中的has_permission方法与has_object_permission方法。

from rest_framework.permissions import BasePermissionclass MyPermission(BasePermission):# 判断对使用此权限类的视图是否有访问权限def has_permission(self, request, view):# 任何用户对使用此权限类的视图都没有访问权限return True# 判断对使用此权限类视图某个数据对象是否有访问权限def has_object_permission(self, request, view, obj):# 对id为1,3的数据对象有访问权限print(obj)if obj.id in (1, 3):return Truereturn False

使用自定义权限类

class TestView(ModelViewSet):queryset = User.objects.all()serializer_class = UserSerializer# 指定当前视图的认证方案,不使用全局认证方案# authentication_classess = [BasicAuthentication, SessionAuthentication]# 指定当前视图的权限控制方案,不使用全局权限控制方案# permission_classes = [IsAuthenticated]# 使用自定义的权限控制类permission_classes = [MyPermission]

使用TokenAuthentication身份验证

在Django REST Framework中,可以使用TokenAuthentication来进行身份验证。TokenAuthentication是基于令牌的身份验证方式,通过向每个用户分配唯一的令牌来识别用户。当用户发送请求时,他们需要在请求头中包含该令牌以进行身份验证。

配置

在settings.py文件中配置

在INSTALLED_APPS中添加rest_framework.authtoken应用程序

INSTALLED_APPS = ['rest_framework.authtoken',
]

在REST_FRAMEWORK中配置认证与权限类

REST_FRAMEWORK = {'DEFAULT_RENDERER_CLASSES': [# 设置使用JSON渲染器'rest_framework.renderers.JSONRenderer',],'DEFAULT_AUTHENTICATION_CLASSES': [# 使用TokenAuthentication认证'rest_framework.authentication.TokenAuthentication',],'DEFAULT_PERMISSION_CLASSES': [# 使用IsAuthenticated权限类确保已登录用户才能访问API'rest_framework.permissions.IsAuthenticated',],
}

执行数据库迁移

1.在项目根目录下执行命令来生成迁移文件

python manage.py makemigrations

2.运行命令来应用最新的数据库迁移

python manage.py migrate

3.如果曾经手动删除authtoken_token表,请将该表重新创建。通过运行命令来创建该表

python manage.py migrate rest_framework.authtoken

注意: 在进行数据库迁移之前,请务必备份数据库以避免数据丢失。

创建一个认证令牌

先创建一个john用户对象,然后获取john用户对象,使用该对象创建一个Token对象。最后就可以使用这个Token来进行API请求的认证。

# 设置Django运行所依赖的环境变量
import osfrom django.test import TestCaseif not os.environ.get('DJANGO_SETTINGS_MODULE'):os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_demo.settings')# 让Django进行一次初始化
import djangodjango.setup()from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import Userclass MyTest(TestCase):# User.objects.create(username='john', password='password')user = User.objects.get(username='john')token = Token.objects.create(user=user)print(token)

创建视图

创建一个MyView视图,然后添加身份验证

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticatedclass MyView(APIView):permission_classes = [IsAuthenticated]def get(self, request):return Response({'username': request.user.username})

配置路由

urlpatterns = [re_path(r'^test/$', views.MyView.as_view(), name='test'),
]

测试

发送请求,Django REST Framework将检查请求头中是否包含有效的令牌,如果是,则允许该请求。
Django REST Framework(DRF)框架之认证Authentication与权限Permission
无效的令牌,拦截。

{"detail": "Authentication credentials were not provided."
}