zoukankan      html  css  js  c++  java
  • DRF教程9-权限

    permissions.py源码分析

    SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
    #GET请求,HEAD获取头部信息,OPTIONS获取可用请求类型设置为安全方法
    #POST,PUT,PATCH,DELETE都会修改数据,没有加到这个元组
    

      

    @six.add_metaclass(BasePermissionMetaclass)
    class BasePermission(object):
        """
        A base class from which all permission classes should inherit.
        """
    
        def has_permission(self, request, view):
            """
            Return `True` if permission is granted, `False` otherwise.
            """
            return True
    
        def has_object_permission(self, request, view, obj):
            """
            Return `True` if permission is granted, `False` otherwise.
            """
            return True
    #所有权限类都该继承它
    #两个方法,has_perm,has_obj_perm
    

      

    class AllowAny(BasePermission):
        """
        Allow any access.
        This isn't strictly required, since you could use an empty
        permission_classes list, but it's useful because it makes the intention
        more explicit.
        """
    
        def has_permission(self, request, view):
            return True
    #允许任何访问
    #不是严格需要,因为可以使用空的权限类,但它会使代码更清晰
    

      

    class IsAuthenticated(BasePermission):
        """
        Allows access only to authenticated users.
        """
    
        def has_permission(self, request, view):
            return bool(request.user and request.user.is_authenticated)
    #只要认证用户允许访问
    #重写了has_permission方法,返回(用户为真)和(用户被认证为真)的与值
    

      

    class IsAdminUser(BasePermission):
        """
        Allows access only to admin users.
        """
    
        def has_permission(self, request, view):
            return bool(request.user and request.user.is_staff)
    #只允许管理员用户访问
    #is_staff是users表里的一个字段
    

      

    class IsAuthenticatedOrReadOnly(BasePermission):
        """
        The request is authenticated as a user, or is a read-only request.
        """
    
        def has_permission(self, request, view):
            return bool(
                request.method in SAFE_METHODS or
                request.user and
                request.user.is_authenticated
            )
    #认证用户的请求,或者只读请求
    #请求方法在SAFE_METHODS 这个元组里则返回True
    #请求用户为认证用户也返回True
    

      

    class DjangoModelPermissions(BasePermission):
        """
        The request is authenticated using `django.contrib.auth` permissions.
        See: https://docs.djangoproject.com/en/dev/topics/auth/#permissions
    
        It ensures that the user is authenticated, and has the appropriate
        `add`/`change`/`delete` permissions on the model.
    
        This permission can only be applied against view classes that
        provide a `.queryset` attribute.
        """
    
        # Map methods into required permission codes.
        # Override this if you need to also provide 'view' permissions,
        # or if you want to provide custom permission codes.
        perms_map = {
            'GET': [],
            'OPTIONS': [],
            'HEAD': [],
            'POST': ['%(app_label)s.add_%(model_name)s'],
            'PUT': ['%(app_label)s.change_%(model_name)s'],
            'PATCH': ['%(app_label)s.change_%(model_name)s'],
            'DELETE': ['%(app_label)s.delete_%(model_name)s'],
        }
    
        authenticated_users_only = True
    
        def get_required_permissions(self, method, model_cls):
            """
            Given a model and an HTTP method, return the list of permission
            codes that the user is required to have.
            """
            kwargs = {
                'app_label': model_cls._meta.app_label,
                'model_name': model_cls._meta.model_name
            }
    
            if method not in self.perms_map:
                raise exceptions.MethodNotAllowed(method)
    
            return [perm % kwargs for perm in self.perms_map[method]]
    
        def _queryset(self, view):
            assert hasattr(view, 'get_queryset') 
                or getattr(view, 'queryset', None) is not None, (
                'Cannot apply {} on a view that does not set '
                '`.queryset` or have a `.get_queryset()` method.'
            ).format(self.__class__.__name__)
    
            if hasattr(view, 'get_queryset'):
                queryset = view.get_queryset()
                assert queryset is not None, (
                    '{}.get_queryset() returned None'.format(view.__class__.__name__)
                )
                return queryset
            return view.queryset
    
        def has_permission(self, request, view):
            # Workaround to ensure DjangoModelPermissions are not applied
            # to the root view when using DefaultRouter.
            if getattr(view, '_ignore_model_permissions', False):
                return True
    
            if not request.user or (
               not request.user.is_authenticated and self.authenticated_users_only):
                return False
    
            queryset = self._queryset(view)
            perms = self.get_required_permissions(request.method, queryset.model)
    
            return request.user.has_perms(perms)
    #使用django.contrib.auth权限认证请求
    #确保用户被认证,并且在model上拥有合适的add,change,delete的权限
    #只有在有queryset属性的类视图上使用
    #
    #perms_map
    #映射方法到权限码
    #如果要提供view权限,或者自定义权限码,重写它
    #每个method对应一个列表,格式是app_label.codename,比如cmdb.add_gameid
    #
    #get_required_permissions
    #输入一个model和http方法
    #如果method没有在perms_map映射表,则抛出错误
    #返回权限列表
    #
    #_queryset
    #检查视图中有没有queryset属性或者get_queryset方法,没有则报错。
    #
    #has_permission
    #检查有没有权限
    #如果view中定义_ignore_model_permissions则直接返回True
    #如果账户没有认证,则返回False
    #将用户拥有的权限返回
    

      

    class DjangoModelPermissionsOrAnonReadOnly(DjangoModelPermissions):
        """
        Similar to DjangoModelPermissions, except that anonymous users are
        allowed read-only access.
        """
        authenticated_users_only = False
    #继承自DjangoModelPermissions
    #改变一个参数,允许匿名用户的只读访问
    

      

    全局设置

        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.AllowAny',
        ),
    #在rest_framework/settings.py中,默认的权限配置AllowAny
    
    REST_FRAMEWORK = {
        ...
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.DjangoModelPermissions',
        ),
    }
    #可以在项目的settings中,修改为DjangoModelPermissions,这是最常用的
    

      

    局部设置

      只允许认证用户访问,只对这个viewset生效

    from rest_framework.permissions import IsAuthenticated
    
    class SvrconfigViewSet(viewsets.ReadOnlyModelViewSet):
        """
        retrieve:
            返回指定信息
        list:
            返回列表
        """
        queryset = Svrconfig.objects.all()
        serializer_class = SvrconfigSerializer
        permission_classes = (IsAuthenticated,)
    #给一个视图集设置权限,只有认证用户可以访问
    #没有用户信息,会出现401错误
    

      

    get权限

    在DjangoModelPermissions中,默认get是不需要权限的,但业务中的查看一般是需要权限的所以需要重写。

    project/permissions.py

    #重建权限映射
    from rest_framework.permissions import DjangoModelPermissions
    
    
    class Permissions(DjangoModelPermissions):
    
        perms_map = {
            'GET': ['%(app_label)s.view_%(model_name)s'],
            'OPTIONS': [],
            'HEAD': [],
            'POST': ['%(app_label)s.add_%(model_name)s'],
            'PUT': ['%(app_label)s.change_%(model_name)s'],
            'PATCH': ['%(app_label)s.change_%(model_name)s'],
            'DELETE': ['%(app_label)s.delete_%(model_name)s'],
        }
    

      

    settings.py

    REST_FRAMEWORK = {
        ...
        'DEFAULT_PERMISSION_CLASSES': (
            'project.permissions.Permissions',
        ),
    }
    

      

      

  • 相关阅读:
    Tsql 获取服务器信息
    数据字典生成脚本 【转载】
    c# winform文本框数字,数值校验
    ReentrantLock和AbstractQueuedSynchronizer的分析
    多线程
    前缀和与差分数组
    链表
    堆(优先队列)
    排序算法
    二分查找(递归和非递归)
  • 原文地址:https://www.cnblogs.com/jabbok/p/10857838.html
Copyright © 2011-2022 走看看