zoukankan      html  css  js  c++  java
  • django--权限(1)初识

    一、权限表结构设计

    1、认识权限

      生活中处处有权限,比如,腾讯视频开会员才有观看某个最新电影的权限,你有房间钥匙就有了进入这个房间的权限,等等。同样,程序开发过程中也有权限,我们今天说的权限指的是web网站权限,对于不同用户访问web服务时应该有不同的功能,如,一个公司有CEO、销售主管、销售等等,不同的用户能访问的服务也不是完全相同的,所以这个时候就需要权限控制了。

    2、为什么要开发权限组件

      组件可以减少重复开发,一次开发,在以后的项目中可以一直使用,避免重复写同样的代码。

    3、web开发中权限是指什么?

      web程序是通过 url 的切换来查看不同的页面(功能),所以权限指的其实就是一个含有正则表达式的URL,对url控制就是对权限的控制。

      结论:一个人有多少个权限就取决于他有多少个URL的访问权限。

    4、权限表结构设计(简单版)

      根据实际情况,一般一个用户可以有多个权限,一个权限也可以分配给多个用户,所以表结构可以按照如下设计:

    用户表                          权限表         
    id      name                   id    user_id       url                     title
         alex                    1       1       /customer/add              添加客户
         egon                    2       1       /customers/list/           查看客户
          1       /consult_records/add/      添加跟进记录
          1       /consult_records/          查看跟进记录

    分析:设计完之后思考一下这样做有什么问题?假设又新增了10个用户,每个用户都有右表中的4个权限,那就要在权限表中新增40条记录,这还是只有4个url的情况,现实生活中一个web网站肯定不止4个url,这意味着每增加一个用户,你就要在权限表中增加若干条记录,加重了程序员的工作不说,这样造成了数据库空间的严重浪费,那么思考一下如何改进!

    5、权限表设计(第二版)

      聪明的你一定有想法了,没错,如果对用户进行划分角色,然后对角色进行权限的分配,问题就解决了。

      分析:

        一个人可以有多个角色

        一个角色可以有多个人

        一个角色可以有多个权限

        一个权限可以分配给多个角色

      表结构设计:

    用户表:user                        user2role表
    id   name                          id      user_id    role_id
       alex                           1          1         3
       egon                           2          2         3
    
    
    角色表:role                      role2permission
    id     title                     id        role_id            permission_id
         CEO                       1            3                  1
         销售总监                  2            3                  2
         销售                    3            3                  3
               3                  4
    
    权限表:permission
    id          url                     title
           /customer/add              添加客户
           /customers/list/           查看客户
           /consult_records/add/      添加跟进记录
           /consult_records/          查看跟进记录

    经过调整之后,由原来的【基于用户的权限控制】转换成【基于角色的权限控制】,以后再进行分配权限时只需要给指定角色分配一次权限,给众多用户再次分配指定角色即可。

      models.py中代码如下:

    from django.db import models
    
    # Create your models here.
    class User(models.Model):
        """
        用户表
        """
        name = models.CharField(verbose_name='用户名', max_length=32)
        password = models.CharField(verbose_name='密码', max_length=32)
        roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role')
        def __str__(self):
            return self.name
    
    class Role(models.Model):
        """
        角色表
        """
        title = models.CharField(verbose_name='角色名称', max_length=32)
        permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission')
        def __str__(self):
            return self.title
    
    class Permission(models.Model):
        """
        权限表
        """
        url = models.CharField(verbose_name='含正则的URL', max_length=32)
        title = models.CharField(verbose_name='标题', max_length=32)
        
        def __str__(self):
            return self.title

     不经意间,我们居然设计出了一个经典的权限访问控制系统:rbac(Role-Based Access Control)基于角色的权限访问控制。

      注意:现在的设计还不是最终版,但之后的设计都是在此版本基础上扩增的,为了能够更好的理解,我们暂且在此基础上继续开发,直到遇到无法满足的情况,再进行整改。

    二、客户管理之权限控制

    1、首先按照上面model示例代码建表,进行数据库迁移,在admin.py中注册表,然后再创建一个超级用户,登录admin录入数据,如下:

    2、修改admin的显示格式,以permission表为例:

      在admin.py中,permission表的注册方法admin.site.register(Permission)改为如下代码:

    # 自定义类,类名自己定,但必须继承ModelAdmin
    class PermissionConfig(admin.ModelAdmin):  
        list_display = ['pk', 'title', 'url']
        ordering = ['pk']  # 按照主键从低到高
    
    admin.site.register(Permission, PermissionConfig)

    Permission表显示效果如下,有没有更直观:

       注意:使用django的admin添加数据时,一定要记得在admin.py中注册你自己的表,否则登录admin只能看见django自带的表,看不见你自己在model中定义的表。

    3、登录视图函数

    def login(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            user_obj = User.objects.filter(name=user, password=pwd).first()
            if user_obj:
                request.session['user_id'] = user_obj.pk  # 将用户id注入session
                # 查询当前登录人的所有权限列表
                ret = Role.objects.filter(user=user_obj).values('permissions__url').distinct()
    
                permission_list = []
                for item in ret:
                    permission_list.append(item['permissions__url'])
                print('权限列表', permission_list)
                # 将当前登录人的权限列表注入session中
                request.session['permission_list'] =  permission_list
    
                return HttpResponse('登录成功')
            
        return render(request, 'login.html')

    4、控制权限的中间件

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import redirect, HttpResponse
    import re
    
    class PermissionMiddleWare(MiddlewareMixin):
        def process_request(self, request):
    
            # 设置白名单放行
            for reg in ["/login/", "/admin/*"]:
                ret = re.search(reg, request.path)
                if ret:
                    return None
    
            # 检验是否登录
            user_id = request.session.get('user_id')
            if not user_id:
                return redirect('/login/')
    
            # 检验权限
            permission_list = request.session.get('permission_list')
            for reg in permission_list:
                reg = '^%s$' % reg
                ret = re.search(reg, request.path)
                if ret:
                    return None
            return HttpResponse('无权访问')

    三、补充

    1、django的配置文件相关

      django中其实有两个配置文件,一个是我们项目中可以看见的settings.py文件,也就是用户的配置文件,另一个是django默认的配置文件global_settings.py,你有没有注意到虽然有些参数我们在自己的配置文件settings.py中虽然没有定义,但其实他是有值的,没错,django是在默认的配置文件中为我们写好了,同时允许我们在自己的setting.py中重新定义覆盖掉django默认值,由此得出用户的配置文件优先级比django默认的高,因此,我们知道了项目的配置参数由django和我们自己定义的配置文件共同决定的,且django的默认配置文件包含我们自己定义的配置文件,所以,当我们导入配置文件时,应以如下方式:

    from django.conf import settings
  • 相关阅读:
    子集生成——增量构造法+位向量法+二进制法
    记忆化搜索
    欧拉回路和欧拉通路
    拓扑排序(基于dfs+基于队列)
    HDU 3839 Ancient Messages(DFS)
    【gulp】前端自动化工具---gulp的使用(一)------【巷子】
    【面向对象】用大白话扯扯那"神奇"的面向对象之方法继承(五)------【巷子】
    【面向对象】----【prototype&&__proto__&&实例化对象三者之间的关系】(四)-----【巷子】
    【面向对象】用大白话扯扯那"神奇"的面向对象之属性继承(三)------【巷子】
    【面向对象】用大白话扯扯那"神奇"的面向对象编程思维(二)------【巷子】
  • 原文地址:https://www.cnblogs.com/wxj1129549016/p/9993436.html
Copyright © 2011-2022 走看看