认证与权限

在完成 RESTful Web API 搭建之后,似乎主要工作已经完成。大家仔细想想,还有没遗漏什么?对了,现在的接口任何人都可以访问,试想,一个任何人都能够访问的师生管理系统,如果被别有用心的人利用,岂不是会造成一定的隐患?再看周围的一些系统,是不是大多都需要登陆后才能使用,而另外一些系统,不同的用户登陆,操作权限又不同,那这些又是如何实现的呢。这一小节,我们就来介绍在 Django REST framework 中如何实现 RESTful Web API 的认证和权限分配。

1.认证功能的使用

通常,我们可以在设置文件中配置全局默认的认证方案,一旦配置,全局默认采用配置的认证方案

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

另外,我们也可以为不同的视图分别指定不同的认证方案,此时可在视图中通过 authentication_classes指定:

from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView

class ExampleView(APIView):
    authentication_classes = (SessionAuthentication, BasicAuthentication)
    ...

认证成功,即可获取接口内容,而认证失败,通常会有两种可能的返回值:

  • 401 Unauthorized 未认证;

  • 403 Permission Denied 权限被禁止(配合权限使用)。

2.权限功能的使用

权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

我们可以在配置文件中设置默认的权限管理类,一旦配置,全局默认采用配置的认证方案:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}

如果在全局设置文件中没有配置权限,则采用默认的配置:

'DEFAULT_PERMISSION_CLASSES': (
   'rest_framework.permissions.AllowAny',
)

与认证类似,也可以在视图中通过 permission_classes 属性来设置权限类,如

from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class ExampleView(APIView):
    permission_classes = (IsAuthenticated,)
    ...

3. Django Rest framework为我们提供的权限:

  • AllowAny:允许所有用户;
  • IsAuthenticated:仅通过认证的用户;
  • IsAdminUser:仅管理员用户;
  • IsAuthenticatedOrReadOnly:认证的用户可以完全操作(增删改查),否则只能读取(查)。

4. 举例

设定如下认证类和权限类,用户只有登录,才可访问 StudentDetailVie 视图提供的接口:

from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import RetrieveAPIView
from AppDemo.models import StudentsModel
from AppDemo.serializers import StudentsSerializer

class StudentDetailView(RetrieveAPIView):
    queryset = StudentsModel.objects.all()
    serializer_class = StudentsSerializer
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]

5. 自定义权限

有时,Django Rest framework 为我们提供的权限无法满足实际需求,我们需要自定义权限,此时只需继承 rest_framework.permissions.BasePermission,并重写以下两个方法:

  • .has_permission(self, request, view)

    是否可以访问视图, view表示当前视图对象

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

    是否可以访问数据对象, view表示当前视图, obj为数据对象

例如:

class CustomPermission(BasePermission):
    def has_object_permission(self, request, view, obj):
        """控制对obj对象的访问权限,我们此时返回False,拒绝任何人的请求"""
        return False

class StudentViewSet(ModelViewSet):
    queryset = StudentsModel.objects.all()
    serializer_class = StudentsSerializer
    permission_classes = [IsAuthenticated, MyPermission]

6. 小结

数据安全是系统的核心要求,因而只有通过认证的用户才能获取关键数据,另外,不同类型数据的敏感程度不同,因而要为不同的认证用户划分可以访问的数据。本节向大家介绍的认证和权限,几乎是构建 API 时一定会用到的,大家要深入理解其中的原理, 才能在使用中融会贯通,得心应手地运用。