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运维平台接口文档"))
]

权限管理 和组织架构 菜单 按钮之间的流程图 权限管理包括_User_02

 

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

权限管理 和组织架构 菜单 按钮之间的流程图 权限管理包括_字段_03

 这样就可访问了!

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

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

权限管理 和组织架构 菜单 按钮之间的流程图 权限管理包括_django_04

 

 但是阅读源码发现它的模型权限中没有添加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中不作任何配置。

权限管理 和组织架构 菜单 按钮之间的流程图 权限管理包括_User_05

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")

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

权限管理 和组织架构 菜单 按钮之间的流程图 权限管理包括_django_06

 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
        }