Django-Rest-Framework 权限管理源码浅析

栏目: Python · 发布时间: 7年前

内容简介:在django的views中不论是用类方式还是用装饰器方式来使用rest框架,django_rest_frame实现权限管理都需要两个东西的配合:上面给出的是权限配置的默认方案,写和不写没有区别。中指定你自己的类即可:

在django的views中不论是用类方式还是用装饰器方式来使用rest框架,django_rest_frame实现权限管理都需要两个东西的配合: authentication_classespermission_classes

# 方式1: 装饰器
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import AllowAny
from rest_framework.response import Response


@api_view(["GET", ])
@permission_classes([AllowAny,])
@authentication_classes([SessionAuthentication, BasicAuthentication])
def test_example(request):
    content = {
            'user': unicode(request.user),  # `django.contrib.auth.User` instance.
            'auth': unicode(request.auth),  # None
        }
        return Response(content)

# ------------------------------------------------------------
# 方式2: 类
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (AllowAny,)

    def get(self, request, format=None):
        content = {
            'user': unicode(request.user),  # `django.contrib.auth.User` instance.
            'auth': unicode(request.auth),  # None
        }
        return Response(content)
复制代码

上面给出的是权限配置的默认方案,写和不写没有区别。 rest框架有自己的settings文件 ,最原始的默认值都可以在里面找到:

Django-Rest-Framework 权限管理源码浅析
说道rest的settings文件,要覆盖其中的默认行为,特别是权限认证行为,我们只需要在 项目settings文件

中指定你自己的类即可:

REST_FRAMEWORK = {
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'your_authentication_class_path',
    ),
    ...
}
复制代码

在rest的settings文件中,获取属性时,会优先加载项目的settings文件中的设置,如果项目中没有的,才加载自己的默认设置:

  • 初始化api_settings对象
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
复制代码
  • APISettings 类中获取属性时优先获取项目的settings文件中 REST_FRAMEWORK 对象的值,没有的再找自己的默认值
@property
def user_settings(self):
    if not hasattr(self, '_user_settings'):
        # _user_settings默认为加载项目settings文件中的REST_FRAMEWORK对象
        self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
    return self._user_settings

def __getattr__(self, attr):
    if attr not in self.defaults:
        raise AttributeError("Invalid API setting: '%s'" % attr)

    try:
        # Check if present in user settings
        # 优先加载user_settings,即项目的settings文件,没有就用默认
        val = self.user_settings[attr]
    except KeyError:
        # Fall back to defaults
        val = self.defaults[attr]

    # Coerce import strings into classes
    if attr in self.import_strings:
        val = perform_import(val, attr)

    # Cache the result
    self._cached_attrs.add(attr)
    setattr(self, attr, val)
    return val
复制代码

在rest中settings中,能自动检测 项目settings 的改变,并重新加载自己的配置文件:

Django-Rest-Framework 权限管理源码浅析

权限管理原理浅析

rest框架是如何使用 authentication_classespermission_classes ,并将二者配合起来进行权限管理的呢?

  • 使用类方式实现的时候,我们都会直接或间接的使用到rest框架中的APIVIEW,在 urls.py 中使用该类的 as_view 方法来构建router
# views.py
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated


class ExampleAPIView(APIView):
    permission_classes = (IsAuthenticated,)
    ...
    
# -----------------------------
from django.conf.urls import url, include

from .views import ExampleAPIView

urlpatterns = [
    url(r'^example/(?P<example_id>[-\w]+)/examples/?$',
        ExampleAPIView.as_view()),
]

复制代码
  • 在我们调用 APIVIEW.as_view() 的时候,该类会调用父类的同名方法:

    Django-Rest-Framework 权限管理源码浅析
  • 父类的同名方法中,调用了dispatch方法:

    Django-Rest-Framework 权限管理源码浅析
  • rest 重写 了该方法,在该方法中对requset做了一次服务端初始化(加入验证信息等)处理

    Django-Rest-Framework 权限管理源码浅析
    调用权限管理
    Django-Rest-Framework 权限管理源码浅析

在权限管理中会使用默认的或是你指定的权限认证进行验证: 这里只是做验证并存储验证结果 ,这里操作完后authentication_classes的作用就完成了。验证结果会在后面指定的 permission_classes 中使用!

def get_authenticators(self):
        """
        Instantiates and returns the list of authenticators that this view can use.
        """
        return [auth() for auth in self.authentication_classes]
复制代码

通过指定的permission_classes确定是否有当前接口的访问权限:

class IsAuthenticatedOrReadOnly(BasePermission):
    """
    The request is authenticated as a user, or is a read-only request.
    """

    def has_permission(self, request, view):
        return (
            request.method in SAFE_METHODS or
            request.user and
            request.user.is_authenticated
        )
复制代码

最后,不管有没有使用permission_classes来决定是否能访问,默认的或是你自己指定的authentication_classes都会执行并将权限结果放在request中!


以上所述就是小编给大家介绍的《Django-Rest-Framework 权限管理源码浅析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Alone Together

Alone Together

Sherry Turkle / Basic Books / 2011-1-11 / USD 28.95

Consider Facebookit’s human contact, only easier to engage with and easier to avoid. Developing technology promises closeness. Sometimes it delivers, but much of our modern life leaves us less connect......一起来看看 《Alone Together》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器