zoukankan      html  css  js  c++  java
  • 一.8.django权限管理/drf权限管理

    1.什么是权限管理:
    .权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源
    .权限管理好比如钥匙,有了钥匙就能把门打开,但是权限设置是有级别之分的,假如这个系统有多个权限级别就如一间屋有多个门,想要把所有门都打开您必须要取得所有的钥匙,就如系统一样。

    2.django权限机制:
      django权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活;用好权限机制,能让系统更加强大和健壮

    3.django权限控制:
      Django用user, group和permission完成了权限机制,这个权限机制是将属于model的某个permission赋予user或group,可以理解为全局的权限,即如果用户A对数据模型(model)B有可写权限,那么A能修改model B的所有实例(objects)。group的权限也是如此,如果为group C 赋予model B的可写权限,则隶属于group C 的所有用户,都可以修改model B的所有实例。

    4.Django的权限项:
      Django用permission对象存储权限项,每个model默认都有三个permission,即add model, change model和delete model
      permission总是与model对应的,如果一个object不是model的实例,我们无法为它创建/分配权限

    5.默认权限:
      在 INSTALLED_APPS 设置中列出 django.contrib.auth 后,安装的各个应用中的每个 Django 模型默认都有三个权限:添加、修改和删除。每次运行 manage.py migrate 命令  创建新模型时都会为其赋予这三个权限。

    6.分组:

      django.contrib.auth.models.Group 模型是为用户分类的通用方式,这样便可以为一批用户赋予权限或添加其 他标注。用户所属的分组数量不限。一个分组中的用户自动获得赋予那个分组的权限。

      除了权限之外,分组还是为用户分类的便捷方式,分组后可以给用户添加标签,或者扩展功能

    7.权限应用:

    Permission

    User Permission

    Group Permission

    8.权限检查

    Permission:

      .Django定义每个model后,默认都会添加该model的add, change和delete三个permission,自定义的permission可以在我们定义model时手动添加

    class Server(models.Model):

        ...    

        class Meta:        

            permissions = (            

                ("view_server", "can view server"),            

                ("change_server_status", "Can change the status of server"),        

            )

      .每个permission都是django.contrib.auth.Permission类型的实例,该类型包含三个字段name, codename 和 content_type,

    content_type反应了permission属于哪个model,

    codename 如上面的view_server,代码逻辑中检查权限时要用, 

    name是permission的描述,将permission打印到屏幕或页面时默认显示的就是name

    9.User Permission:

    User对象的user_permission字段管理用户的权限:

      user = User.objects.get(username="rock")

      user.user_permissions = [permission_list]

      user.user_permissions.add(permission, permission, …) #增加权限 

      user.user_permissions.remove(permission, permission, …) #删除权限 

      user.user_permissions.clear() #清空权限

      user.get_all_permissions() #列出用户的所有权限

      user.get_group_permissions() # 列出用户所属group的权限

    10.Group Permission:

      group permission管理逻辑与user permission管理一致,group中使用permissions字段做权限管理: 

        group.permissions.set([permission_list])

        group.permissions.add(permission, permission, …) 

        group.permissions.remove(permission, permission, …) 

        group.permissions.clear()

    11.权限验证-普通视图:

      在视图中验证权限—— permission_required

    当业务逻辑中涉及到权限检查时,decorator能够分离权限验证和核心的业务逻辑,使代码更简洁,逻辑更清晰。permission的decorator为permission_required

    from django.contrib.auth.decorators import login_required, permission_required 

    @login_required   --表示你必须要登录

    @permission_required(’dashboard.view_server')  ---表示你必须有权限才可以

    def my_view(request):

        ...

    12.权限验证-类视图:

    from django.utils.decorators import method_decorator

    from django.contrib.auth.decorators import login_required, permission_required

    class ServerView(TemplateView):

        @method_decorator(login_required)

        @method_decorator(permission_required(“dashboard.view_server”)

        def get(self, request, *args, **kwargs):

            ...

    13.权限验证-view代码中验证:

    if not request.user.has_perm(’dashboard.view_server')

        return HttpResponse('Forbidden')

    14.权限验证-模板中验证:

      验证是否有登陆 {% if user.is_authenticated %} <p>Welcome, {{ user.username }}. Thanks for logging in.</p> {% else %} <p>Welcome, new user. Please log in.</p> {% endif %}

      验证是否有权限 {% if perms.dashboard.view_server %} 有权限 {% endif %}

    15.自定义PermissionRequiredMixin: 创建仅限 .在模型的 Meta 类中定制权限 class Meta: permissions = ( ("modify_user_status", "修改用户状态"), ("modify_user_passwd", "修改用户密码"), ) 

     一.drf权限管理

    1.简单权限应用---只有登录过的用户才能访问

    (1).apps/users/views.py:

    from django.shortcuts import render
    from rest_framework import viewsets
    from django.contrib.auth import get_user_model
    from .serializers import UserSerializer
    from .filters import UserFilter
    from rest_framework.permissions import IsAuthenticated
    
    User = get_user_model()
    class UserViewset(viewsets.ReadOnlyModelViewSet):
        '''
        这个用户资源的viewset会给外面暴露两个接口retrieve和list
        retrieve:返回指定用户信息对象--单个对象的字段是在用户序列化类serializers.py中定义
         list:返回用户列表--列表的字段的字段是在用户序列化类serializers.py中定义
        '''
        #1.指定queryset
        queryset = User.objects.all()
        #2.指定序列化类
        serializer_class = UserSerializer
        #(2)按哪个字段搜索:
        filter_fields = ('username',"email")
        #(3)使用哪个filter类
        filter_class = UserFilter
        #权限为必须得登录才能认证:
        permission_classes = (IsAuthenticated,)

    效果如下图:

    那怎么认证?--得用drf的认证

      drf提供了一套基于原始的认证即session认证,它的认证是只需配一登录页面即可。

    (2)devops/urls.py中添加一路由:

    urlpatterns = [
        url(r'^', include(route.urls)),
        url(r'^aip-auth', include("rest_framework.urls",namespace="reset_framework")),
        url(r'^docs/', include_docs_urls("lizhihua运维平台接口文档"))
    ]

    (python36env) [vagrant@CentOS7 devops]$ python manage.py createsuperuser
    Username (leave blank to use 'vagrant'): admin
    Email address: admin@51reboot.com
    Password: 123456 

     这样就可访问了!

    2.全局权限应用--模型权限(必须跟模型关联):

      查看权限源码文件如下图中可知它已对内置很很多权限,那这样我就可自定义权限继承其中任何一权限类即可:

     但是阅读源码发现它的模型权限中没有添加get认证/权限验证,只有如下方法有权限验证:

    class DjangoModelPermissions(BasePermission):
        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'],
        }
    ........

    (1)settins.py:配置全局模型权限

    查看参考源码配置如下图:但是allowany所有人均可访问不是我要的,所以我覆盖它默认配置--改为django的模型权限,这样就全局生效,好处是不用在每个app的视图中都写,但不好的是如果你一但写一个filter,没有queryset就会出错--解决:就是在app中自定不使用全局的,使用自己独立的即可,这里先使用全局的即可,只做如下配置,app的views.py中不作任何配置。

    REST_FRAMEWORK = {
     'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
        'PAGE_SIZE':10,
        'DEFAULT_PAGINATION_CLASS':'users.pagination.Pagination',
        'DEFAULT_FILTER_BACKENDS': (
            'django_filters.rest_framework.DjangoFilterBackend',
        ),
     'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.DjangoModelPermissions',
        ],
    }
    创建普通用户
    (python36env) [vagrant@CentOS7 devops]$ python manage.py shell
    n [1]: from django.contrib.auth.models import User                  
    
    In [2]: User.objects.create_user("rock","rock@51reboot.com","123456")

    登录后效果如下:--所有的测试页面都只有看的权限

     3.drf自定义get权限

      因为django默认支持的模型权限中没有get的,所以我可直接自定并覆盖它默认的,

     (1)devops/permissions.py中:

    from rest_framework.permissions import DjangoModelPermissions
    
    class Permissions(DjangoModelPermissions):
        #
        def get_custom_perms(self, view, method):
            if hasattr(view, "extra_perm_map"):
                if isinstance(view.extra_perm_map, dict):
                    return view.extra_perm_map.get(method,[])
            return []
    
        #这个方法必须写,我是直接把django模型权限中的必备的has_permission方法拷过来
        def has_permission(self, request, view):
            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)
            perms.extend(self.get_custom_perms(view, request.method))
            return request.user.has_perms(perms)

    (2)全局配置替换掉:

    REST_FRAMEWORK = {
     'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
        'PAGE_SIZE':10,
        'DEFAULT_PAGINATION_CLASS':'users.pagination.Pagination',
        'DEFAULT_FILTER_BACKENDS': (
            'django_filters.rest_framework.DjangoFilterBackend',
        ),
     'DEFAULT_PERMISSION_CLASSES': [
            # 'rest_framework.permissions.DjangoModelPermissions',
            'devops.permissions.Permissions',
        ]
    }

     4.不使用queryset即模型的权限---viewset权限

    class DashboardStatusViewset(viewsets.ViewSet):
        """
        list:
        获取dashboard状态数据
        """
        permission_classes = (permissions.IsAuthenticated,)
        def list(self, request, *args, **kwargs):
            data = self.get_content_data()
            return response.Response(data)
    
        def get_content_data(self):
            return {
                "aa": 11,
                "bb": 22
            }
  • 相关阅读:
    一段代码让你了解匿名函数的来龙去脉
    橡皮擦背景色橡皮擦魔术橡皮擦
    flv播放器
    测试面试题01
    java中堆和栈的区别
    经典javaThead 生产者 消费者
    判断一个点是否在三个点组成的三角形内 java 代码 面试经典
    软件项目管理面试题
    java中的位运算
    真正的JDBC java代码
  • 原文地址:https://www.cnblogs.com/dbslinux/p/13132030.html
Copyright © 2011-2022 走看看