权限
# 链接资料
博客园极其内向的帅小伙
drf官方文档
drf官方源码地址
GitHub - encode/django-rest-framework: Web APIs for Django. 🎸 (opens new window)
功能大致脑图
# 1. 权限基本使用
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。
- 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
- 在通过get_object()获取具体对象时,会进行对象访问权限的判断
# 1.1 使用
可以在配置文件中设置默认的权限管理类,如
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
1
2
3
4
5
2
3
4
5
如果未指明,则采用如下默认配置
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
1
2
3
2
3
也可以在具体的视图中通过permission_classes属性来设置,如
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
...
1
2
3
4
5
6
2
3
4
5
6
# 1.2 提供的权限
# AllowAny 允许所有用户
# IsAuthenticated 仅通过认证的用户
# IsAdminUser 仅管理员用户
# IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取
# 1.3 举例
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import RetrieveAPIView
class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
authentication_classes = [SessionAuthentication]
permission_classes = [IsAuthenticated]
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 2. APIView权限管理源码剖析
我们现在还是看看 ApiView的源码,学过django的人都知道,ApiView 继承了 View ,然后重写 了 dispatch 方法。废话不多说了,我们先来追踪 到到底在哪里。追踪还是一样 Ctrl 按键 + 类名或者方法名等。
generics.ListCreateAPIView -> GenericAPIView -> views.APIView => 找到 dispatch方法。
1
我们找到APIView中的 dispatch 方法:
class APIView(View):
def dispatch(self, request, *args, **kwargs):
....
try:
self.initial(request, *args, **kwargs)
.....
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
好啦,我们看到有一个 self. initial 方法。我们继续点击去看看 : Ctrl 按键 + self.initial:
class APIView(view):
....
def initial(self, request, *args, **kwargs):
.....
# Ensure that the incoming request is permitted
self.perform_authentication(request) #检查认证
self.check_permissions(request) #检查权限
self.check_throttles(request)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
先认证再做了权限
self.check_permissions -> get_permissions() -> self.permission_classes -> api_settings -> DEFAULTS
1
DEFAULTS = {
....
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny', #在这里,这边啥权限没做,任何人都可以操作
),
...
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 3. 自定义权限
自定义权限主要是重写
IsAuthenticatedOrReadOnly => BasePermission
1
BasePermission源码如下:
写权限类,通过获取数据库的用户类型返回True,False(True表示可以访问)
@six.add_metaclass(BasePermissionMetaclass)
class BasePermission(object):
"""
A base class from which all permission classes should inherit.
"""
def has_permission(self, request, view): #数据获取方法,get方法
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True
def has_object_permission(self, request, view, obj): #数据更新和删除权限,我们要重写这个方法
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 示例
说明:编辑 permissions.py文件
示例1
from rest_framework import permissions #导入权限模块
class IsOwnOrReadOnly(permissions.BasePermission):
#重写has_object_permission方法
def has_object_permission(self, request, view, obj): #obj表示当前数据对象(models中 User对象)
if request.method in permissions.SAFE_METHODS: #SAFE_METHOD:安全方法
return True
#print("obj", obj) #测试 obj,是当前模型(models)对象。返回的默认值是 models中 str() 方法的返回值
#print("request", request)
return obj.user == request.user # 创建用户的数据(obj.user) 是否跟 当前用户(request.user) 一样
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
示例二
# 写权限类,通过获取数据库的用户类型返回True,False(True表示可以访问)
# app02.utils.permission.py
class Mypermission(permissions.BasePermission):
"""管理员"""
def has_permission(self, request, value):
if request.user.user_type == 2:
return True
return Falses
class Mypermission01(permissions.BasePermission):
"""普通用户管理用户都可以访问"""
def has_permission(self, request, value):
if request.user.user_type != 2:
return True
return True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
局部使用
views.py
# 使用
from .utils.permission import Mypermission01,Mypermission
class OrderView(APIView):
permission_classes = [Mypermission01, ]
def get(self, request, *args, **kwargs):
ret = {'code': 1000, 'message': 'ok!', 'data': None}
try:
ret['data'] = ORDER_DICT
except Exception as e:
ret['code'] = 1001
ret['message'] = '找不到服务器'
return JsonResponse(ret)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
全局使用
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES':['app02.utils.permission.Mypermission'] # 管理才可以访问(权限)
}
1
2
3
2
3
编辑 (opens new window)
← 认证 接口访问控制(限流)→