Django RBAC权限管理设计过程详解


Posted in Python onAugust 06, 2019

一.权限简介

1. 问:为什么程序需要权限控制?

答:生活中的权限限制,① 看灾难片电影《2012》中富人和权贵有权登上诺亚方舟,穷苦老百姓只有等着灾难的来临;② ?潘棵牵?忻挥邢牍??裁茨切┏さ闷?辽聿暮玫墓媚镌谀闵肀卟淮嬖谀兀恳蛭?星?撕推?凉媚锒际钦涔笙∮械模?∮械娜嗽谝黄鹜嫠:徒馑?髦肿耸啤6?悖?奕ㄓ涤兴?牵?荒茏约和孀约毫恕?br />

程序开发时的权限控制,对于不同用户使用系统时候就应该有不同的功能,如:

  • 普通员工
  • 部门主管
  • 总监
  • 总裁

所以,只要有不同角色的人员来使用系统,那么就肯定需要权限系统。

2. 问:为什么要开发权限组件?

答:假设你今年25岁,从今天开始写代码到80岁,每年写5个项目,那么你的一生就会写275个项目,保守估计其中应该有150+个都需要用到权限控制,为了以后不再重复的写代码,所以就开发一个权限组件以便之后55年的岁月中使用。 亲,不要太较真哦,你觉得程序员能到80岁么,哈哈哈哈哈哈哈

偷偷告诉你:老程序员开发速度快,其中一个原因是经验丰富,另外一个就是他自己保留了很多组件,新系统开发时,只需把组件拼凑起来基本就可以完成。

3. 问:web开发中权限指的是什么?

答:web程序是通过 url 的切换来查看不同的页面(功能),所以权限指的其实就是URL,对url控制就是对权限的控制。

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

二.权限表结构设计:第一版

问答环节中已得出权限就是URL的结论,那么就可以开始设计表结构了。

  • 一个用户可以有多个权限。
  • 一个权限可以分配给多个用户。

你设计的表结构大概会是这个样子:

Django RBAC权限管理设计过程详解

现在,此时此刻是不是觉得自己设计出的表结构棒棒哒!!!

But,无论是是否承认,你还是too young too native,因为老汉腚眼一看就有问题....

问题:假设 “maple”和“ffm” 这俩货都是老板,老板的权限一定是非常多。那么试想,如果给这俩货分配权限时需要在【用户权限关系表中】添加好多条数据。假设再次需要对老板的权限进行修改时,又需要在【用户权限关系表】中找到这俩人所有的数据进行更新,太他妈烦了吧!!! 类似的,如果给其他相同角色的人来分配权限时,必然会非常繁琐。

三.权限表结构设计:第二版

聪明机智的一定在上述的表述中看出了写门道,如果对用户进行角色的划分,然后对角色进行权限的分配,这不就迎刃而解了么。

  • 一个人可以有多个角色。
  • 一个角色可以有多个人。
  • 一个角色可以有多个权限。
  • 一个权限可以分配给多个角色。

表结构设计:

Django RBAC权限管理设计过程详解

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

from django.db import models
class Permission(models.Model):
  """
  权限表
  """
  title = models.CharField(verbose_name='标题', max_length=32)
  url = models.CharField(verbose_name='含正则的URL', max_length=128)

  def __str__(self):
    return self.title
class Role(models.Model):
  """
  角色
  """
  title = models.CharField(verbose_name='角色名称', max_length=32)
  permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)
  def __str__(self):
    return self.title
class UserInfo(models.Model):
  """
  用户表
  """
  name = models.CharField(verbose_name='用户名', max_length=32)
  password = models.CharField(verbose_name='密码', max_length=64)
  email = models.CharField(verbose_name='邮箱', max_length=32)
  roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role', blank=True)

  def __str__(self):
    return self.name

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

四.客户管理之动态“一级”菜单

from django.db import models
class Permission(models.Model):
  """
  权限表
  """
  title = models.CharField(verbose_name='标题', max_length=32)
  url = models.CharField(verbose_name='含正则的URL', max_length=128)
  icon = models.CharField(verbose_name='图标', max_length=32, null=True, blank=True, help_text='菜单才设置图标')
  is_menu = models.BooleanField(verbose_name='是否是菜单', default=False)

  def __str__(self):
    return self.title
class Role(models.Model):
  """
  角色
  """
  title = models.CharField(verbose_name='角色名称', max_length=32)
  permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)

  def __str__(self):
    return self.title
class UserInfo(models.Model):
  """
  用户表
  """
  name = models.CharField(verbose_name='用户名', max_length=32)
  password = models.CharField(verbose_name='密码', max_length=64)
  email = models.CharField(verbose_name='邮箱', max_length=32)
  roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role', blank=True)
  def __str__(self):
    return self.name

五.客户管理之动态“二级”菜单

from django.db import models
class Menu(models.Model):
  """
  菜单
  """
  title = models.CharField(verbose_name='菜单', max_length=32)
  icon = models.CharField(verbose_name='图标', max_length=32)
  def __str__(self):
    return self.title
class Permission(models.Model):
  """
  权限表
  """
  title = models.CharField(verbose_name='标题', max_length=32)
  url = models.CharField(verbose_name='含正则的URL', max_length=128)
  menu = models.ForeignKey(verbose_name='菜单', to='Menu', null=True, blank=True, help_text='null表示非菜单')
  def __str__(self):
    return self.title
class Role(models.Model):
  """
  角色
  """
  title = models.CharField(verbose_name='角色名称', max_length=32)
  permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)
  def __str__(self):
    return self.title
class UserInfo(models.Model):
  """
  用户表
  """
  name = models.CharField(verbose_name='用户名', max_length=32)
  password = models.CharField(verbose_name='密码', max_length=64)
  email = models.CharField(verbose_name='邮箱', max_length=32)
  roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role', blank=True)
  def __str__(self):
    return self.name

六.客户管理之默认展开非菜单URL

from django.db import models
class Menu(models.Model):
  """
  菜单
  """
  title = models.CharField(verbose_name='菜单', max_length=32)
  icon = models.CharField(verbose_name='图标', max_length=32)
  def __str__(self):
    return self.title
class Permission(models.Model):
  """
  权限表
  """
  title = models.CharField(verbose_name='标题', max_length=32)
  url = models.CharField(verbose_name='含正则的URL', max_length=128)

  pid = models.ForeignKey(verbose_name='默认选中权限', to='Permission', related_name='ps', null=True, blank=True,
              help_text="对于无法作为菜单的URL,可以为其选择一个可以作为菜单的权限,那么访问时,则默认选中此权限",
              limit_choices_to={'menu__isnull': False})  
  menu = models.ForeignKey(verbose_name='菜单', to='Menu', null=True, blank=True, help_text='null表示非菜单')
  def __str__(self):
    return self.title
class Role(models.Model):
  """
  角色
  """
  title = models.CharField(verbose_name='角色名称', max_length=32)
  permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)
  def __str__(self):
    return self.title
class UserInfo(models.Model):
  """
  用户表
  """
  name = models.CharField(verbose_name='用户名', max_length=32)
  password = models.CharField(verbose_name='密码', max_length=64)
  email = models.CharField(verbose_name='邮箱', max_length=32)
  roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role', blank=True)
  def __str__(self):
    return self.name

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python对指定目录下文件进行批量重命名的方法
Apr 18 Python
Python获取某一天是星期几的方法示例
Jan 17 Python
Python 快速实现CLI 应用程序的脚手架
Dec 05 Python
关于Django显示时间你应该知道的一些问题
Dec 25 Python
微信跳一跳python自动代码解读1.0
Jan 12 Python
Python3之读取连接过的网络并定位的方法
Apr 22 Python
Python模拟简单电梯调度算法示例
Aug 20 Python
Appium+python自动化之连接模拟器并启动淘宝APP(超详解)
Jun 17 Python
tensorflow实现打印ckpt模型保存下的变量名称及变量值
Jan 04 Python
解决Python 异常TypeError: cannot concatenate 'str' and 'int' objects
Apr 08 Python
Python实现学生管理系统并生成exe可执行文件详解流程
Jan 22 Python
Python获取指定日期是"星期几"的6种方法
Mar 13 Python
python虚拟环境完美部署教程
Aug 06 #Python
python批量图片处理简单示例
Aug 06 #Python
Python实用库 PrettyTable 学习笔记
Aug 06 #Python
浅谈django2.0 ForeignKey参数的变化
Aug 06 #Python
Python中调用其他程序的方式详解
Aug 06 #Python
运用PyTorch动手搭建一个共享单车预测器
Aug 06 #Python
基于python实现自动化办公学习笔记(CSV、word、Excel、PPT)
Aug 06 #Python
You might like
php生成SessionID和图片校验码的思路和实现代码
2009/03/10 PHP
PHP 事务处理数据实现代码
2010/05/13 PHP
让PHP显示Facebook的粉丝数量方法
2014/01/08 PHP
PHP is_subclass_of函数的一个BUG和解决方法
2014/06/01 PHP
php-app开发接口加密详解
2018/04/18 PHP
javascript XML数据显示为HTML一例
2008/12/23 Javascript
Javascript string 扩展库代码
2010/04/09 Javascript
jquery获取table中的某行全部td的内容方法
2013/03/08 Javascript
js 字符串转换成数字的三种方法
2013/03/23 Javascript
js字母大小写转换实现方法总结
2013/11/13 Javascript
浅谈在Vue-cli里基于axios封装复用请求
2017/11/06 Javascript
完美解决手机网页中输入框被输入法遮挡的问题
2017/12/19 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
2019/07/26 Javascript
jQuery实现动态向上滚动
2020/12/21 jQuery
python实现查询苹果手机维修进度
2015/03/16 Python
解密Python中的描述符(descriptor)
2015/06/03 Python
python提取图像的名字*.jpg到txt文本的方法
2018/05/10 Python
读取json格式为DataFrame(可转为.csv)的实例讲解
2018/06/05 Python
python中ASCII码字符与int之间的转换方法
2018/07/09 Python
python Selenium实现付费音乐批量下载的实现方法
2019/01/24 Python
Python3.5装饰器典型案例分析
2019/04/30 Python
如何利用Python开发一个简单的猜数字游戏
2019/09/22 Python
如何基于Python实现电子邮件的发送
2019/12/16 Python
利用setuptools打包python程序的方法步骤
2020/01/18 Python
Vision Directa智利眼镜网:框架眼镜、隐形眼镜和名牌太阳眼镜
2016/11/23 全球购物
全球第二大家装零售商:Lowe’s
2018/01/13 全球购物
EJB2和EJB3在架构上的不同点
2014/09/29 面试题
MYSQL相比于其他数据库有哪些特点
2013/07/19 面试题
毕业生应聘幼儿园的自荐信
2013/11/20 职场文书
优秀的茶餐厅创业计划书
2014/01/03 职场文书
三个儿子教学反思
2014/02/03 职场文书
颁奖晚会主持词
2014/03/25 职场文书
读书活动总结
2014/04/28 职场文书
党的群众路线专项整治方案
2014/11/03 职场文书
2016年社区中秋节活动总结
2016/04/05 职场文书
win10+anaconda安装yolov5的方法及问题解决方案
2021/04/29 Python