Django rest framework 权限操作(源码分析)

这一篇是基于上一篇写的,上一篇谢了认证的具体流程,看懂了上一篇这一篇才能看懂,

当用户访问是 首先执行dispatch函数,当执行当第二部时:

   #2.处理版本信息 处理认证信息 处理权限信息 对用户的访问频率进行限制
            self.initial(request, *args, **kwargs)

进入到initial方法:

def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.
        #2.1处理版本信息
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        #2.2处理认证信息
        self.perform_authentication(request)
        #2.3处理权限信息
        self.check_permissions(request)
        #2.4对用户的访问频率进行限制
        self.check_throttles(request)
#2.3处理权限信息
        self.check_permissions(request)

下面 开始 权限的具体分析:

进入到check_permissions函数中

#检查权限
    def check_permissions(self, request):
        """
        Check if the request should be permitted.
        Raises an appropriate exception if the request is not permitted.
        """
        #elf.get_permissions()得到的是一个权限对象列表
        for permission in self.get_permissions():
            #在自定义的Permission中has_permission方法是必须要有的
            #判断当前has_permission返回的是True,False,还是抛出异常
            #如果是True则表示权限通过,False执行下面代码
            if not permission.has_permission(request, self):
                #为False的话则抛出异常,当然这个异常返回的提示信息是英文的,如果我们想让他显示我们自定义的提示信息
                #我们重写permission_denied方法即可
                self.permission_denied(
                    #从自定义的Permission类中获取message(权限错误提示信息),一般自定义的话都建议写上,如果没有则为默认的(英文提示)
                    request, message=getattr(permission, 'message', None)
                )

查看permission_denied方法(如果has_permission返回True则不执行该方法)

def permission_denied(self, request, message=None):
        """
        If request is not permitted, determine what kind of exception to raise.
        """
        if request.authenticators and not request.successful_authenticator:
            #没有登录提示的错误信息
            raise exceptions.NotAuthenticated()
        #一般是登陆了但是没有权限提示
        raise exceptions.PermissionDenied(detail=message)

举例:

from django.db import models

# Create your models here.
class Userinfo(models.Model):
    name=models.CharField(max_length=32,verbose_name='用户名')
    pwd=models.CharField(max_length=32,verbose_name='密码')
    token=models.CharField(max_length=64,null=True)

    def __str__(self):
        return self.name

models
urlpatterns = [
    url(r'^p/', app02_views.Pview.as_view()),
    url(r'^mp/', app02_views.Aview.as_view()),
    url(r'^jp/', app02_views.Jview.as_view()),
]
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from rest_framework.response import Response
from rest_framework import exceptions


from app01 import models
# Create your views here.

class MyAuthentication(BaseAuthentication):

    def authenticate(self, request):
        token=request.query_params.get('token')
        user=models.Userinfo.objects.filter(token=token).first()
        if user:
            return (user.name,user)
        return None

class MyPermission(object):
    message = '登录才可以访问'
    def has_permission(self,request, view):
        if request.user:
            return True
        return False

class AdminPermission(object):
    message = '会员才可以访问'
    def has_permission(self,request,view):
        if request.user=='ctz':
            return True
        return False

class Pview(APIView):
    '''
    所有人都可以看
    '''
    authentication_classes = [MyAuthentication,]
    permission_classes = []
    def get(self,request):
        return Response('图片列表')
    def post(self,request):
        pass




class Aview(APIView):
    '''
    登录的人可以看
    '''
    authentication_classes = [MyAuthentication,]
    permission_classes = [MyPermission,]
    def get(self,request):
        return Response('美国电影列表')
    def post(self,request):
        pass

    def permission_denied(self, request, message=None):
        """
        If request is not permitted, determine what kind of exception to raise.
        """

        if request.authenticators and not request.successful_authenticator:
            raise exceptions.NotAuthenticated('无权访问')
        raise exceptions.PermissionDenied(detail=message)

class Jview(APIView):
    '''
    会员才可以看
    '''
    authentication_classes = [MyAuthentication,]
    permission_classes = [MyPermission,AdminPermission,]
    def get(self,request):
        return Response('日本电影列表')
    def post(self,request):
        pass

    def permission_denied(self, request, message=None):
        """
        If request is not permitted, determine what kind of exception to raise.
        """

        if request.authenticators and not request.successful_authenticator:
            raise exceptions.NotAuthenticated('无权访问')
        raise exceptions.PermissionDenied(detail=message)

Views

上面的是局部的只能在当前类中可以用,如果想在全局中用:只需要在settings中配置即可:

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from rest_framework.response import Response
from rest_framework import exceptions

from app02.utils import MyPermission
#
#
from app01 import models
# # Create your views here.
#
# class MyAuthentication(BaseAuthentication):
#
#     def authenticate(self, request):
#         token=request.query_params.get('token')
#         user=models.Userinfo.objects.filter(token=token).first()
#         if user:
#             return (user.name,user)
#         return None
#
# class MyPermission(object):
#     message = '登录才可以访问'
#     def has_permission(self,request, view):
#         if request.user:
#             return True
#         return False
#
# class AdminPermission(object):
#     message = '会员才可以访问'
#     def has_permission(self,request,view):
#         if request.user=='ctz':
#             return True
#         return False

class Pview(APIView):
    '''
    所有人都可以看
    '''

    permission_classes = []
    def get(self,request):
        return Response('图片列表')
    def post(self,request):
        pass




class Aview(APIView):
    '''
    登录的人可以看
    '''
  #  authentication_classes = [MyAuthentication,]
    permission_classes = [MyPermission,]
    def get(self,request):
        return Response('美国电影列表')
    def post(self,request):
        pass

    def permission_denied(self, request, message=None):
        """
        If request is not permitted, determine what kind of exception to raise.
        """

        if request.authenticators and not request.successful_authenticator:
            raise exceptions.NotAuthenticated('无权访问')
        raise exceptions.PermissionDenied(detail=message)

class Jview(APIView):
    '''
    会员才可以看
    '''
    # authentication_classes = [MyAuthentication,]
    # permission_classes = [MyPermission,AdminPermission,]
    def get(self,request):
        return Response('日本电影列表')
    def post(self,request):
        pass

    def permission_denied(self, request, message=None):
        """
        If request is not permitted, determine what kind of exception to raise.
        """

        if request.authenticators and not request.successful_authenticator:
            raise exceptions.NotAuthenticated('无权访问')
        raise exceptions.PermissionDenied(detail=message)

Views
from django.shortcuts import render

from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from rest_framework.response import Response
from rest_framework import exceptions
from rest_framework.exceptions import APIException


from app01 import models
# Create your views here.

class MyAuthentication(BaseAuthentication):

    def authenticate(self, request):
        token=request.query_params.get('token')
        user=models.Userinfo.objects.filter(token=token).first()
        if user:
            return (user.name,user)
        return None

class MyPermission(object):
    message = '登录才可以访问'
    def has_permission(self,request, view):
        if request.user:
            return True
        return False

class AdminPermission(object):
    message = '会员才可以访问'
    def has_permission(self,request,view):
        if request.user=='ctz':
            return True
        return False

utils
REST_FRAMEWORK = {
    'UNAUTHENTICATED_USER': None,
    'UNAUTHENTICATED_TOKEN': None,
    "DEFAULT_AUTHENTICATION_CLASSES": [
      # "app01.utils.MyAuthentication",
        "app02.utils.MyAuthentication",
    ],
    "DEFAULT_PERMISSION_CLASSES":[
       "app02.utils.MyPermission",
       "app02.utils.AdminPermission",
    ],
}

settings
原文地址:https://www.cnblogs.com/sunxiuwen/p/9979478.html