当前位置:   article > 正文

Django REST 框架详解 09 | 权限组件_django permission_classes

django permission_classes

一、权限组件

1. 分析源码

通过分析源码了解权限组件的方法调用过程

APIView 的 dispatch 中使用 initial 方法实现初始化并进行三大认证,第二步进行权限组件调用

rest_framework/views.py

class APIView(View):
    # ...
    # 定义默认权限类
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    def initial(self, request, *args, **kwargs):
        # ...
        # 认证组件:校验用户
        # 这里调用 perform_authentication 实现认证
        self.perform_authentication(request)
        # 权限组件:校验用户权限
        self.check_permissions(request)
        # 频率组件:限制视图接口被访问次数
        self.check_throttles(request)    
    
    # 权限认证
    def check_permissions(self, request):        
       # 遍历权限对象列表得到一堆权限器,进行权限认证
        for permission in self.get_permissions():
            # 权限类 has_permission 做权限认证
            # 参数:权限对象self,请求对象request,视图类对象
            # 返回值:有权限返回 True,无权限返回 False
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request, message=getattr(permission, 'message', None)
                )
                
     # 获取权限
     def get_permissions(self):
        # 由权限类定义
        return [permission() for permission in self.permission_classes]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

在 drf 设置文件查看默认权限配置

rest_framework/settings.py

# 默认权限类配置
DEFAULTS = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

查看默认系统权限的实现

rest_framework/permissions.py

class AllowAny(BasePermission):
    """
    Allow any access.
    This isn't strictly required, since you could use an empty
    permission_classes list, but it's useful because it makes the intention
    more explicit.
    """
	# 游客与登录用户都拥有所有权限
    def has_permission(self, request, view):
        return True
    
    class IsAuthenticated(BasePermission):
    """
    Allows access only to authenticated users.
    """

    def has_permission(self, request, view):
        # 只有合法用户有权限,游客无任何权限:
        # 有值且认证通过
        return bool(request.user and request.user.is_authenticated)
	
class IsAdminUser(BasePermission):
	# is_staff:后台管理用户
    # 后台管理用户由所有权限,游客无权限
    def has_permission(self, request, view):
        return bool(request.user and request.user.is_staff)
    
class IsAuthenticatedOrReadOnly(BasePermission):
    def has_permission(self, request, view):
        return bool(
            # 如果是读请求,不校验用户,直接返回
            request.method in SAFE_METHODS or
            # 登录用户有所有权限,游客只读
            request.user and
            request.user.is_authenticated
        )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

总结以上的系统权限类:

  • AllowAny:游客与登录用户有所有权限

  • IsAuthenticated:登录用户有所有权限,游客无权限

  • IsAdminUser:后台管理用户由所有权限,游客无权限

  • IsAuthenticatedOrReadOnly:登录用户有所有权限,游客只读

2. 全局配置权限

settings.py

# 全局局部配置
REST_FRAMEWORK = {
    # 配置默认权限类
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
3. 局部配置权限

views.py

from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import GenericViewSet, ViewSet

from utils.response import APIResponse

# 只有登录后才能访问
# 这里认证用的是之前的 MyAuthentication
class AuthenticatedAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        return APIResponse(0, 'Authenticated successful')

# 游客只读,用户无限制
class AuthenticatedOrReadOnlyAPIView(APIView):
    permission_classes = [IsAuthenticatedOrReadOnly]

    def get(self, request, *args, **kwargs):
        return APIResponse(0, 'Read successful')

    def post(self, request, *args, **kwargs):
        return APIResponse(0, 'All successful')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

urls.py

from django.conf.urls import url
from api import views

urlpatterns = [
    url(r'^auth/$', views.AuthenticatedAPIView.as_view()),
    url(r'^auth2/$', views.AuthenticatedOrReadOnlyAPIView.as_view()),
]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
4. 接口测试

只有登录后才能访问
mark

登录用户和游客可读
mark

登录用户有所有权限
mark

二、自定义权限类

1. 代码实现
  • 继承 BasePermission

  • 重写 has_permission 方法

  • 实现根据自定义权限规则,确定是否有权限

  • 认证规则:

    • 满足设置的用户条件,代表有权限,返回 True
    • 不满足设置的用户条件,代表无权限,返回 False
  • 进行全局或局部配置

    • 全局:配置文件 settings.py
    • 局部:在视图类 import
  • 测试接口:前台在请求头携带认证信息,且默认规范用 Authorization 字段携带认证信息

自定义权限类permissions.py

from rest_framework.permissions import BasePermission, SAFE_METHODS
from django.contrib.auth.models import Group

class MyPermission(BasePermission):

    def has_permission(self, request, view):
        # values_list(falt=True) 获取列表转为集合,与目标求交集
        group = Group.objects.filter(name='administrator').first()
        groups = request.user.groups.all()
        return bool(
            request.method in ('GET', 'HEAD', 'OPTIONS') or
            group and groups and
            group in groups
        )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

views.py

from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import GenericViewSet, ViewSet

from api.permissions import MyPermission
from utils.response import APIResponse

# 游客和登录用户只读,登录用户属于管理员分组无限制
class AdminOrReadOnlyAPIView(APIView):
    permission_classes = [MyPermission]

    def get(self, request, *args, **kwargs):
        return APIResponse(0, 'Mypermission Read successful')

    def post(self, request, *args, **kwargs):
        return APIResponse(0, 'Mypermission All successful')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

urls.py

from django.conf.urls import url
from api import views

urlpatterns = [
    url(r'^login/$', views.LoginView.as_view()),
    url(r'^auth/$', views.AuthenticatedAPIView.as_view()),
    url(r'^auth2/$', views.AuthenticatedOrReadOnlyAPIView.as_view()),
    url(r'^auth3/$', views.AdminOrReadOnlyAPIView.as_view()),
]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
2. 测试接口

有认证信息且正确,有所有权限
mark

无认证信息,或有错误认证信息,无写权限
mark

无认证信息,有读权限
mark

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/71628
推荐阅读
相关标签
  

闽ICP备14008679号