权限管理---设计分析以及具体细节

说起权限我们大家都知道,不一样的角色会有不一样的权限。

比如就像学生管理系统一样,管理员,老师,学生之间的权限都是不一样的,那么展示的页面也是不一样的。

所以,我们现在来看看具体操作。

目标:生成一个独立的组件,到哪都能用!(是不是很厉害)

步骤

一、先创建一个项目,建立一个app01和rbac的应用

二、表结构的设计

  1、先看配置文件合适不,给创建的rbac在配置文件里面设置一下
    找到INSTALLED_APPS=['rbac']

  

  2、 表结构设计      

    models中创建类:五个类,七张表
    角色表:
    用户表:
    权限表:

    权限组表:

    菜单表:

    角色表和权限表是多对多的关系(一个角色可以有多个权限,一个权限可以对应多个角色)
    用户表和角色表是多对多的关系(一个用户可以有多个角色,一个角色有多个用户)

    所以有会多生成两张关系表

    一个菜单下面有多个组

    一个组下面有多个权限

    一个菜单下面有多个权限

 

from django.db import models

# Create your models here.
class Role(models.Model):
title = models.CharField(max_length=32,verbose_name="角色")
permissions = models.ManyToManyField(to="Permission",verbose_name="拥有权限的角色",blank=True) #权限和角色是多对多的关系 def __str__(self):
return self.title
class Meta:
verbose_name_plural = "角色表" class Permission(models.Model):
title = models.CharField(max_length=32,verbose_name="权限名")
url = models.CharField(max_length=32,verbose_name="带正则的url")
codes = models.CharField(max_length=32,verbose_name="代码")
group = models.ForeignKey(to="Group",verbose_name="所属组",blank=True) #组和权限是一对多的关系,一个组有多个权限
menu_gp = models.ForeignKey(to='Permission',related_name='aaa',null=True,blank=True,verbose_name="组内菜单")
def __str__(self):
return self.title
class Meta:
verbose_name_plural = "权限表" class UserInfo(models.Model):
name = models.CharField(max_length=32,verbose_name="姓名")
password = models.CharField(max_length=64,verbose_name="密码")
email = models.CharField(max_length=32,verbose_name="邮箱")
roles = models.ManyToManyField(to="Role",blank=True) #用户和角色是多对多的关系
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "用户表" class Group(models.Model):
title = models.CharField(max_length=32,verbose_name="组名称")
menu = models.ForeignKey(to="Menu",verbose_name="组内菜单",blank=True) #一个组下有多个菜单
def __str__(self):
return self.title
class Meta:
verbose_name_plural = "权限组" class Menu(models.Model):
caption = models.CharField(max_length=32,verbose_name="菜单")
def __str__(self):
return self.caption
class Meta:
verbose_name_plural = "菜单表"

为什么要多加个code列和权限组表呢?

1、我们一般是先看到的是列表页面,在这个页面上是否显示添加,是否显示编辑,是否显示删除,

都是需要判断的有无添加权限,有无删除权限,有无编辑权限,我们可以给每一个url一个代号

dict = {
1:{                 代号
  /userinfo/     list
       /userinfo/add/       add
       /userinfo/del(\d+)/    del
       /userinfo/edit(\d+)/    edit
    }
  }

不仅在列表页面需要知道他有那些权限,在其他页面也知道他有那些权限
所以上面的方案还是有点不好,那么我们采取下面的方案。将代号取出来放在一个列表里面

dict = {
      1:{
      "codes":["list","add","del","edit"]
         urls:[
                "/userinfo/",
                "/userinfo/add"/,
                "/userinfo/del(\d+)/ ",
                "/userinfo/edit(\d+)/ ",
              ]
        }
      2:{
           "codes":{"list","add","del","edit"}
            urls:[
                 "/order",
                 "/order/add"/,
                 "/order/del(\d+)/ ",
                 "/order/edit(\d+)/ ",
               ]
       }
}

把这个字典存到session中
当你访问页面的时候我就知道你有什么权限
一个url对应一个code 
多个url对应一个组

注意:
  关联字段 null = True        数据库用的时候可以为空
  关联字段 blank = True     admin用的时候可以为空

当出现错误

解决办法:

python manage.py migrate --fake 废弃

三、通过django-admin录入权限数据

- 先创建一个超级用户 python3 manage.py createsuperuser
    - 用户名 root
    - 密码 root1234
    - 在admin.py 中
       from rbac import models
       admin.site.register(models.Permission)
       admin.site.register(models.Role)
       admin.site.register(models.UserInfo)
      这样的话上去的是英文的,如果你想让中文显示就在类中加一个类
       class Meta:
       verbose_name_plural = "权限表"
      - 当你给关联字段录入数据的时候会有错误提示,那么在类中你的那个关联字段在加一个属性blank = True 可以为空
      permissions = models.ManyToManyField(to="Permission",verbose_name="具有的所有权限", blank=True)

四、编写登录

1.编写登录
2.如果用户验证成功就设置session
3.先查出当前用户的所有的权限
4.从这些权限中找到所有的url,把这些url放到session中
   这些都是在rbac里面的操作,如果我们做一些复杂的操作,可能会有好多的代码
 我们写rbac的目的是做成一个公共的组件,为了让别人省事
 我们在创建一个server的文件夹,里面创建一个init_permission的py文件。

 结构化数据:方便以后做操作。。。

dict = {
      1:{
      "codes":["list","add","del","edit"]
         urls:[
                "/userinfo/",
                "/userinfo/add"/,
                "/userinfo/del(\d+)/ ",
                "/userinfo/edit(\d+)/ ",
              ]
        }
      2:{
           "codes":{"list","add","del","edit"}
            urls:[
                 "/order",
                 "/order/add"/,
                 "/order/del(\d+)/ ",
                 "/order/edit(\d+)/ ",
               ]
       }
}

5.拿到用户请求的url去session里面做验证
  获取当前请求的url
  获取session中保存当前用户的权限
  然后开始验证
  如果匹配成功就有权访问
  如果匹配不成功就无权访问
  用re去匹配的时候,re.match(/userinfo/,/userinfo/add) #都能匹配到
  那么要记得在匹配正则的时候加个起始符和终止符regex = "^{0}$".format(url)
  def login(request):
    .....
    设置session
  def index(request):
    ....
    获取session
  def userinfo(request):
    获取session
这样如果有好多个函数,就的重复好多代码,我们可以用中间件来处理
中间件和装饰器的区别:
  中间件用来做批量处理
  如果函数不多的话可以用加装饰器的方法

五、中间件:获取session,并且当用户匹配成功的时候,先把code保存在request中,方便以后判断

1、要设置表名单

2、必须继承MiddlewareMixin这个类

class MiddlewareMixin(object):
def __init__(self, get_response=None):
self.get_response = get_response
super(MiddlewareMixin, self).__init__() def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response

六、设计权限管理-----问题:在访问列表页面时,是否需要判断有无添加权限、有无删除权限、有无编辑权限。

views.py

def userinfo(request):
# 方式一
# Page_permission = request.permission_code_list
# 方式二:实例化
page_permission = BasePagePermission(request.permission_code_list)
print("page_permission",request.permission_code_list)
data_list = [
{"id":1,"name":"xxx1"},
{"id":2,"name":"xxx2"},
{"id":3,"name":"xxx3"},
{"id":4,"name":"xxx4"},
{"id":5,"name":"xxx5"},
]
return render(request,"userinfo.html",{"data_list":data_list,"page_permission":page_permission})

在模板userinfo.html中:两种使用方式

方式一:

<table>
{% if "add" in Page_permission %}
<a href="#">添加</a>
{% endif %}
{% for row in data_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
{% if "edit" in Page_permission %}
<td><a href="#">编辑</a></td>
{% endif %}
{% if "del" in Page_permission %}
<td>{<a href="#">删除</a></td>
{% endif %}
</tr>
{% endfor %}
</table>

如果不想每一个都判断,就用方式二

方式二:

把permission_code_list处理一下
在views中定义一个类
class BasePagePermission(object):
def __init__(self,code_list):
self.code_list = code_list
def has_add(self):
if "add" in self.code_list:
return True
def has_del(self):
if "del" in self.code_list:
return True
def has_edit(self):
if "edit" in self.code_list:
return True
实例化:page_permission = BasePagePermission(request.permission_code_list)
在模板中
<table>
{% if page_permission.has_add %}
<a href="#">添加</a>
{% endif %}
{% for row in data_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
{% if page_permission.has_edit %}
<td><a href="#">编辑</a></td>
{% endif %}
{% if page_permission.has_del %}
<td>{<a href="#">删除</a></td>
{% endif %}
</tr>
{% endfor %}
</table>

七、设计菜单管理

1、如何生成菜单

2、怎么让这些菜单分级显示并且如果当前访问的url权限默认展开如果是组内菜单就加粗或者变红

3、非菜单url,默认选中原菜单。(如果你是点击用户列表进来的,那么你看到页面了,

   如果你点击添加的时候,你的那个用户列看不见了,这就不好了。

所以要设计当你点击添加按钮的时候,那个用户列表被默认选中)

菜单管理
  菜单一
    用户管理
    权限管理
  菜单二
    订单管理
    角色管理

分级做了菜单。这些菜单该显示什么菜单?是当前用户登录之后从数据库拿到这个用户拥有的权限,然后把权限搞成菜单

在表里面设计了一个组内菜单(自关联 ),当menu_gp_id为NULL就代表可以作为菜单

1、在初始化的时候,初始化权限信息,获取权限信息并放置在session中

menu_list = []
for item in permission_list:
tpl = {
"id":item["permissions__id"],
"title":item["permissions__title"],
"url":item["permissions__url"],
"menu_gp_id":item["permissions__menu_gp_id"],
"menu_id":item["permissions__group__menu_id"],
"menu_title":item["permissions__group__menu__caption"]
}
menu_list.append(tpl)
request.session[settings.PERMISSION_MENU_KEY] = menu_list

因为是要在页面上渲染,一般我们会在视图函数的render里面加{"":变量}这样渲染,
但是还有个更好用的方法:用自定义的标签

具体操作:
  1、找到app创建一个templatetags的文件夹
  2、然后在里面随便创建一个文件
  3、导入form django.template import Library
       register = Library()

      方式一:
        @register.simple_tag
        def menu():
          return "菜单"     这里返回啥页面上就显示啥
        然后在母版里面导入mnue.html
        {% load rbac %}

      方式二:
        @register.includsion_tag("xxx.html") #这里存放的是html文件,,,@register.includsion_tag("xxx.html")   自动会读这个文件并且把返回值拿到在页面上渲染
        def menu():
          return "菜单"     这里返回啥页面上就显示啥
        “在母版中:{%menu_html  request%}     request是参数,记得要加上{% load rbac %}

  4、注意:
        如果有两个文件夹同名,避免发生冲突:就再创建一个文件夹包起来

2、去Session中获取菜单相关信息,匹配当前URL,生成菜单

先把和菜单相关的所有字段取出来

menu_list = [
{'id': 1, 'title': '用户列表', 'url': '/userinfo/', 'menu_gp_id': None, 'menu_id': 2, 'menu_title': '菜单二'},
{'id': 2, 'title': '添加用户', 'url': '/userinfo/add/', 'menu_gp_id': 1, 'menu_id': 2, 'menu_title': '菜单二'},
{'id': 3, 'title': '删除用户', 'url': '/userinfo/del/(\\d+)/', 'menu_gp_id': 1, 'menu_id': 2, 'menu_title': '菜单二'},
{'id': 4, 'title': '编辑用户', 'url': '/userinfo/edit/(\\d+)/', 'menu_gp_id': 1, 'menu_id': 2, 'menu_title': '菜单二'},
{'id': 5, 'title': '订单列表','url': '/order/', 'menu_gp_id': None, 'menu_id': 1, 'menu_title': '菜单一'},
{'id': 6, 'title': '添加订单', 'url': '/order/add/', 'menu_gp_id': 2, 'menu_id': 1, 'menu_title': '菜单一'},
{'id': 7, 'title': '删除订单', 'url': '/order/del/(\\d+)/', 'menu_gp_id': 2, 'menu_id': 1, 'menu_title': '菜单一'},
{'id': 8, 'title': '编辑订单', 'url': '/order/edit/(\\d+)/', 'menu_gp_id': 2, 'menu_id': 1, 'menu_title': '菜单一'}
]

然后循环列表找出可以作为菜单的权限

{
1: {'id': 1, 'title': '用户列表', 'url': '/userinfo/', 'menu_gp_id': None, 'menu_id': 2, 'menu_title': '菜单二'},
5: {'id': 5, 'title': '订单列表', 'url': '/order/', 'menu_gp_id': None, 'menu_id': 1, 'menu_title': '菜单一'}
}

再次循环列表向上边的字典中添加active

{
1: {'id': 1, 'title': '用户列表', 'url': '/userinfo/', 'menu_gp_id': None, 'menu_id': 2, 'menu_title': '菜单二', 'active': True},
5: {'id': 5, 'title': '订单列表', 'url': '/order/', 'menu_gp_id': None, 'menu_id': 1, 'menu_title': '菜单一'}
}

结构化数据(吧上面得到的数据化成下面这样格式的,方便以后使用)

{
1: {
'menu_id': 1,
'menu_title': '菜单一',
'active': None,
'children': [
{'title': '订单列表', 'url': '/order/', 'active': None}
]
}
2: {
'menu_id': 2,
'menu_title': '菜单二',
'active': True,
'children': [
{'title': '用户列表', 'url': '/userinfo/', 'active': True}
]
}, }

八、实现

见下篇

基于角色权限管理:rbac设计分析以及具体细节的更多相关文章

  1. 基于角色权限管理:rbac具体代码实现

    权限管理 创建一个rbac和app的应用,这个rbac主要是用来存放权限的,全称叫做基于角色权限控制 一.先看配置文件合适不,给创建的rbac在配置文件里面设置一下 找到INSTALLED_APPS= ...

  2. rbac(基于角色权限控制)-------权限管理

    权限管理 创建一个rbac和app的应用,这个rbac主要是用来存放权限的,全称叫做基于角色权限控制 一.先看配置文件合适不,给创建的rbac在配置文件里面设置一下 找到INSTALLED_APPS= ...

  3. devops-jenkins基于角色的权限管理RBAC

    一. devops-jenkins基于角色的权限管理RBAC 1 安装角色的rbac角色管理  1.1) 点击系统管理 1.2) 选择插件管理 1.3) 选择可选插件,输入role搜索 1.4) 选择 ...

  4. Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架

    Asp.Net Core 2.0 项目实战(1) NCMVC开源下载了 Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架 Asp.Ne ...

  5. 【基于url权限管理 shiro(一)】--基础

    只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源.权限管理包括用户认证和授权两部分.   用户认证 1.概 ...

  6. RDIFramework.NET ━ 9.9 角色权限管理 ━ Web部分

    RDIFramework.NET ━ .NET快速信息化系统开发框架 9.9  角色权限管理 -Web部分 角色权限管理模块主要是对角色的相应权限进行集中设置.在角色权限管理模块中,管理员可以添加或移 ...

  7. Asp.Net Core 2.0 项目实战(3)NCMVC角色权限管理前端UI预览及下载

    Asp.Net Core 2.0 项目实战(1) NCMVC开源下载了 Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架 Asp.Ne ...

  8. Asp.Net MVC+BootStrap+EF6.0实现简单的用户角色权限管理

    这是本人第一次写,写的不好的地方还忘包含.写这个的主要原因是想通过这个来学习下EF的CodeFirst模式,本来也想用AngularJs来玩玩的,但是自己只会普通的绑定,对指令这些不是很熟悉,所以就基 ...

  9. Asp.Net MVC+BootStrap+EF6.0实现简单的用户角色权限管理10

    今天把用户的菜单显示和页面的按钮显示都做好了,下面先来个效果图 接下来说下我实现的方法: 首先我在每个方法前面都加了这个属性, /// <summary> /// 表示当前Action请求 ...

随机推荐

  1. oracle数据库用户创建删除以及数据导入

    dmp文件的导入:1.首先,先创建表空间与用户--创建表空间create tablespace CCFOCUS01datafile 'D:\app\Administrator\oradata\orcl ...

  2. Java常用四大线程池用法以及ThreadPoolExecutor详解

    为什么用线程池? 1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处-理效率 2.线程并发数量过多,抢占系统资源从而导致阻塞 3.对线程进行一些简单的管理 在Java中,线 ...

  3. BZOJ 1647 [Usaco2007 Open]Fliptile 翻格子游戏:部分枚举 位运算

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1647 题意: 在一个n*m(1 <= n,m <= 15)的棋盘上,每一个格子 ...

  4. div img 垂直水平居中

    <style> div { width: 600px; height: 578px; text-align: center; display: table-cell; vertical-a ...

  5. 人工智能实践:TensorFlow 框架

    张量.计算图.会话 基本概念 基于Tensorflow的NN:用张量表示数据,用计算图搭建神经网络,用会话执行计算图,优化线上的权重(参数),得到模型. 张量(Tensor):张量就是多维数组(列表) ...

  6. sulime的必备插件

    常用插件 : SideBarEnhancements HTML-CSS-JS Prettify BracketHighlighter SublimeCodeIntel Emmet CTags Mark ...

  7. Scala Beginner

    开始学习Scala,下面的内容大部分从Scala官网翻译过来,有几个地方翻译的不是很好,表述不清楚的地方大家可以浏览Scala官网,多指教. Scala offical website is http ...

  8. 【250】◀▶IEW-Unit15

    Unit 15 Youth Issues 1.model1题目分析 Young people who are still at school often feel just as much stres ...

  9. CF-811A

    A. Vladik and Courtesy time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  10. CodeForces 287B Pipeline (水题)

    B. Pipeline time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...