认证和权限的区别:

认证:对用户登录的身份进行校验.
权限:对登录验证通过的用户,能够访问的api和对api能取得的对应级别数据做限制

认证

java restful api接口调用权限校验 restful api 权限控制_HTTP


java restful api接口调用权限校验 restful api 权限控制_身份验证_02

BasicAuthentication

使用HTTP基本身份验证,根据用户的用户名和密码进行签名。基本身份验证通常只适用于测试。

SessionAuthentication

使用Django的默认会话后端进行身份验证。会话身份验证适用于与网站在同一会话上下文中运行的Ajax客户端。

TokenAuthentication

使用简单的基于令牌HTTP身份验证。令牌身份验证适用于client-server分离的情况,如本机桌面和移动客户端。

使用Django信号机制自动生成Token

导入信号函数、接收信号receiver和Django User模型类

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from rest_framework.authtoken.models import Token

创建用户时生成Token,打开视图类,添加如下代码:

@receiver(post_save, sender=settings.AUTH_USER_MODEL)  # Django信号机制
def generate_token(sender, instance=None, created=False, **kwargs):
    """
   创建用户时生成Token
   :param sender:
   :param instance:
   :param created: 默认不创建
   :param kwargs:
   :return:
   """
    if created:
        Token.objects.create(user=instance)

用户获取Token

打开**项目路由**``urls.py``
导入``from rest_framework.authtoken import views``
添加路由`` path('api-token-auth/', views.obtain_auth_token)  # 获取Token的接口``
postman进行验证

单独针对某个接口去设置不同的认证方式

对象级别的认证设置优先于全局
装饰器有顺序,要放在api_view()的下面

导入对应包

from rest_framework.decorators import api_view, authentication_classes
from rest_framework.authentication import BasicAuthentication, SessionAuthentication, TokenAuthentication

对接口设置装饰器

java restful api接口调用权限校验 restful api 权限控制_django_03

打开postman,用上面生成的Token和用户名、密码测试一下这个接口,Token应该是请求不通的。

对于类视图、通用类视图、视图集的写法是一样的。

class CourseList(APIView):
    """
    查询课程
    """
    authentication_classes = (BasicAuthentication,)
    
    def get(self, request):
        """

        :param request:
        :return:
        """
        pass

权限

全局设置在上面配置文件已经加过了,下面看下接口权限(对象级别)的权限设置,和认证基本一样。

from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.permissions import IsAuthenticated

接口配置登录权限

java restful api接口调用权限校验 restful api 权限控制_身份验证_04

java restful api接口调用权限校验 restful api 权限控制_身份验证_05


和认证的一样。

自定义对象权限
from rest_framework import permissions


class IsOwnerOrOnlyRead(permissions.BasePermission):
    """自定义权限:只允许对象的所有者能够编辑"""
    
    def has_object_permission(self, request, view, obj):
        """
        所有的request请求都有读权限,因此一律允许GET/HEAD/OPTIONS方法
        :param request: 
        :param view: 
        :param obj: 
        :return: bool
        """
        if request.method in permissions.SAFE_METHODS:  # 点进去可以看到 SAFE_METHODS = ("GET", "HEAD", "OPTIONS")
            return True
        # 对象的所有者才可以拥有读写权限,比如说是你自己的课程你才能修改
        return obj.teacher == request.user

在视图类里添加自定义的权限

java restful api接口调用权限校验 restful api 权限控制_django_06

可以新建一个用户,用postman测试一下。

java restful api接口调用权限校验 restful api 权限控制_身份验证_07


使用test用户请求我们添加过权限的路由地址

java restful api接口调用权限校验 restful api 权限控制_身份验证_08


使用test用户修改、删除课程

java restful api接口调用权限校验 restful api 权限控制_身份验证_09

java restful api接口调用权限校验 restful api 权限控制_django_10

具体视图代码如下

class CourseDetail(APIView):

    authentication_classes = (BasicAuthentication,)
    permission_classes = (IsAuthenticated, IsOwnerOrOnlyRead)
    """
    方便共用对象
    """
    def get_objects(self, pk):
        try:
            obj = Course.objects.get(pk=pk)
            self.check_object_permissions(self.request, obj)
            return obj
        except Course.DoesNotExist:
            return

    """
    查询课程
    """
    def get(self, request, pk):
        """
        :param request:
        :param pk:
        :return:
        """
        obj = self.get_objects(pk=pk)
        if not obj:
            return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        s = CourseSerializer(instance=obj)
        return Response(s.data, status=status.HTTP_200_OK)
    """
     修改课程
    """
    def put(self, request, pk):
        """
        :param request:
        :param pk:
        :return:
        """
        obj = self.get_objects(pk=pk)
        if not obj:
            return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        s = CourseSerializer(instance=obj, data=request.data)
        if s.is_valid():
            s.save()
            return Response(data=s.data, status=status.HTTP_200_OK)
        return Response(data=s.errors, status=status.HTTP_400_BAD_REQUEST)
    """
       删除课程
      """
    def delete(self, request, pk):
        """

        :param request:
        :param pk:
        :return:
        """
        obj = self.get_objects(pk=pk)
        if not obj:
            return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        obj.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

和视图集写法不同的地方是,获取对象公共方法里需要手动调用check_object_permissions方法。