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 当前全局变量和入口参数的所有属性
Jul 01 Python
python类定义的讲解
Nov 01 Python
使用Node.js和Socket.IO扩展Django的实时处理功能
Apr 20 Python
详解在Python程序中解析并修改XML内容的方法
Nov 16 Python
使用Python对MySQL数据操作
Apr 06 Python
python基础练习之几个简单的游戏
Nov 10 Python
python中正则表达式的使用方法
Feb 25 Python
Python对象与引用的介绍
Jan 24 Python
python的一些加密方法及python 加密模块
Jul 11 Python
Flask框架重定向,错误显示,Responses响应及Sessions会话操作示例
Aug 01 Python
Python手绘可视化工具cutecharts使用实例
Dec 05 Python
教你用Python爬取英雄联盟皮肤原画
Jun 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环境配置 php5 MySQL5 apache2 phpmyadmin安装与配置图文教程
2007/03/16 PHP
mysql 中InnoDB和MyISAM的区别分析小结
2008/04/15 PHP
PHP5中GD库生成图形验证码(有汉字)
2013/07/28 PHP
jQuery News Ticker 基于jQuery的即时新闻行情展示插件
2011/11/05 Javascript
jQuery循环滚动展示代码 可应用到文字和图片上
2012/05/11 Javascript
jquery焦点图片切换(数字标注/手动/自动播放/横向滚动)
2013/01/24 Javascript
html5 canvas js(数字时钟)实例代码
2013/12/23 Javascript
jquery.validate.js插件使用经验记录
2014/07/02 Javascript
谈谈对offsetleft兼容性的理解
2015/11/11 Javascript
使用JavaScript解决网页图片拉伸问题(推荐)
2016/11/25 Javascript
vue组件如何被其他项目引用
2017/04/13 Javascript
AngularJS中控制器函数的定义与使用方法示例
2017/10/10 Javascript
深入浅析JS中的严格模式
2018/06/04 Javascript
Three.JS实现三维场景
2018/12/30 Javascript
微信小程序日历弹窗选择器代码实例
2019/05/09 Javascript
解决layui的使用以及针对select、radio等表单组件不显示的问题
2019/09/05 Javascript
ZK中使用JS读取客户端txt文件内容问题
2019/11/07 Javascript
react的hooks的用法详解
2020/10/12 Javascript
[47:42]完美世界DOTA2联赛PWL S2 GXR vs Ink 第一场 11.19
2020/11/20 DOTA
简单了解Python下用于监视文件系统的pyinotify包
2015/11/13 Python
Django实现自定义404,500页面教程
2017/03/26 Python
解决Python中定时任务线程无法自动退出的问题
2019/02/18 Python
8段用于数据清洗Python代码(小结)
2019/10/31 Python
python爬虫利用selenium实现自动翻页爬取某鱼数据的思路详解
2020/12/22 Python
python 写一个水果忍者游戏
2021/01/13 Python
css3动画过渡实现鼠标跟随导航效果
2018/02/08 HTML / CSS
使用CSS3制作版头动画效果
2020/12/24 HTML / CSS
AmazeUI 图标的示例代码
2020/08/13 HTML / CSS
雷蛇美国官网:Razer
2020/04/03 全球购物
自荐书4要点
2014/01/25 职场文书
电工技术比武方案
2014/05/11 职场文书
2014年党员创先争优承诺书
2014/05/29 职场文书
药店收银员岗位职责
2015/04/07 职场文书
解决Golang中ResponseWriter的一个坑
2021/04/27 Golang
Python基础数据类型tuple元组的概念与用法
2021/08/02 Python
淡雅古典唯美少女娇媚宁静迷人写真
2022/03/21 杂记