目录

    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设置

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

    2.2 全局权限控制

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

    settings.py

    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,必须要全部通过才行。

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

    2,使用authentication_classes、permission_classes装饰器。

    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

    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)进行权限的检查。

    def get_object(self):
        obj = get_object_or_404(self.get_queryset())
        self.check_object_permissions(self.request, obj)
        return obj
    

    3. 参考