Please enable Javascript to view the contents

Django REST Framework 权限管理

 ·  ☕ 3 分钟

1. DRF的权限管理

Django REST Framework的权限管理包括两个部分。

  • 一个是认证Authentication方式。指定对用户进行鉴权的方式,获取request.user。
  • 一个是权限控制Permissions。针对Django资源、用户类别进行权限控制。

1.1 认证方式

相关源码在rest_framework/authentication.py文件中。一共有三种认证方式:

  • BasicAuthentication:HTTP基础认证。

前端将用户名和密码以Base64编码的形式,设置在Authorization HTTP头中,后端用以认证用户。

  • TokenAuthentication:基于Token的认证。

使用Authorization HTTP头里面的Token认证用户。

  • SessionAuthentication:使用Djnago的会话后台来认证。

使用Django Session Backend认证用户。

自定义认证方式

DRF还允许自定义认证方式,只需要继承BaseAuthentication类,并实现.authenticate(self, request)方法。

1.2 权限控制方式

相关源码在rest_framework/permissions.py文件中。一共内置了七种权限控制的类别:

  • AllowAny # 无限制。
  • IsAuthenticated # 登陆用户。
  • IsAdminUser # 管理员用户。
  • IsAuthenticatedOrReadOnly # 非登录用户只读。
  • DjangoModelPermissions # Mode级别的控制。
  • DjangoModelPermissionsOrAnonReadOnly # Model匿名只读。
  • DjangoObjectPermissions # 对象级别的控制。

自定义权限控制

继承BasePermission自定义权限控制,实现其中一个或两个方法

  • has_permission(self, request, view),访问这个接口时,会进行权限检测
  • has_object_permission(self, request, view, obj),访问对象时才会进行权限检测

1.3 权限检测后的处理

DRF使用认证类去检测用户执行的请求。

  • 如果认证成功,request.user被设置为认证的User对象。
  • 如果认证失败,request.user被设置为AnonymousUser。

认证失败,返回 HTTP 401,未经授权。

权限检测失败,返回 HTTP 403,权限被拒绝。

2. 权限控制应用

2.1 认证URL设置

1
2
3
urlpatterns = [
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')
]

2.2 全局权限控制

在 settings.py 中可以设置全局默认权限

settings.py

1
2
3
4
5
6
7
8
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
    )
}

2.3 ViewSet 的权限

1,设置 permission_classes 的类属性来给 viewset 设定权限。

DRF 会检查元组内的每一个 premission,必须要全部通过才行。

1
2
3
4
5
class UserViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    authentication_classes = (SessionAuthentication, )
    permission_classes = (permissions.IsAuthenticated,)

2,使用authentication_classes、permission_classes装饰器。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from rest_framework.authentication import SessionAuthentication,
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

@authentication_classes((SessionAuthentication, BasicAuthentication))
@permission_classes((IsAuthenticated,))
def example_view(request, format=None):
    content = {
        'user': unicode(request.user),
        'auth': unicode(request.auth)
    }
    return Response(content)

2.4 自定义权限

定制Permissions, 只需继承BasePermission,然后实现其中一个或两个方法

  • has_permission(self, request, view),访问这个接口时,会进行权限检测
  • has_object_permission(self, request, view, obj),访问对象时才会进行权限检测

premissions.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):

    def has_permission(self, request, view):
        if request.method in permissions.SAFE_METHODS:
            return True

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True

需要注意的是,如果自己实现了get_object,需要使用self.check_object_permissions(self.request, obj)进行权限的检查。

1
2
3
4
def get_object(self):
    obj = get_object_or_404(self.get_queryset())
    self.check_object_permissions(self.request, obj)
    return obj

3. 参考


微信公众号
作者
微信公众号