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

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

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

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

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

步骤

一、先创建一个项目,建立一个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. matlab的一个疑问?

    把逻辑值放入一个已知矩阵,为啥结果是:真就取矩阵的值,假就不取值? K>> aaaa=randi(10,10,2) aaaa = 6 3 10 4 6 7 5 2 6 3 8 2 1 2 ...

  2. TYOI 1015 Game:博弈 结论【步数之和的奇偶性】

    题意: 明明和亮亮在玩一个游戏. 桌面上一行有n个格子,一些格子中放着棋子. 明明和亮亮轮流选择如下方式中的一种移动棋子(图示中o表示棋子,*表示空着的格子): (1)当一枚棋子的右边是空格子的话,可 ...

  3. laravel基础课程---6、请求(如何获取当前 HTTP 请求的实例)

    laravel基础课程---6.请求(如何获取当前 HTTP 请求的实例) 一.总结 一句话总结: 依赖注入:通过依赖注入的方式来获取当前 HTTP 请求的实例:public function sto ...

  4. hdu-2169 Computer(树形dp+树的直径)

    题目链接: Computer Time Limit: 1000/1000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/Others) ...

  5. codeforces 660B B. Seating On Bus(模拟)

    题目链接: B. Seating On Bus time limit per test 1 second memory limit per test 256 megabytes input stand ...

  6. linux命令学习笔记-eval命令详解

    功能说明:重新运算求出参数的内容. 语 法:eval [参数] 补充说明:eval可读取一连串的参数,然后再依参数本身的特性来执行. 参 数:参数不限数目,彼此之间用分号分开. .eval命令将会首先 ...

  7. CF Round #459

    好菜啊 第一场cf就菜成这样...mdzz 可能是我把题看的太简单了吧... T1AC T2AC T3WA T4看错题 T5不会写 T3想的是栈+暴力 正解:  对于一个pretty串的任意一个位置, ...

  8. 【Lintcode】113.Remove Duplicates from Sorted List II

    题目: Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct  ...

  9. 系列文章-- SSIS学习

    SSIS是SQL Server Integraion Services的简称.是生成高性能数据集成解决方案(包括数据仓库的提取.转换和加载 (ETL) 包)的平台.   SSIS组件转换_模糊查找转换 ...

  10. JS极品日历

    <!DOCTYPE><html><head><meta http-equiv="Content-Type" content="t ...