- 简单示意流程图

- RBAC分析:

  - 基于角色的权限管理;

  - 权限等于用户可以访问的URL;

  - 通过限制URL来限制权限;

- RBAC表结构组成:

from django.db import models

class Menu(models.Model):
"""
菜单表:
"""
title = models.CharField(verbose_name='菜单名称', max_length=32, db_index=True) # 创建索引
icon = models.CharField(verbose_name='图标', max_length=32) def __str__(self):
return self.title class Meta:
# db_table = 'menu'
verbose_name = '菜单'
verbose_name_plural = '菜单' class Jurisdiction(models.Model):
"""
权限表
"""
url = models.CharField(max_length=32)
title = models.CharField(verbose_name='权限名称', max_length=32)
name = models.CharField(verbose_name='反向解析别名', max_length=32, unique=True)
menu = models.ForeignKey(to='Menu', null=True, blank=True) def __str__(self):
return self.title class Meta:
verbose_name = '权限'
verbose_name_plural = '权限' class Role(models.Model):
"""
角色表
"""
name = models.CharField(verbose_name='角色名称', max_length=32)
permissions = models.ManyToManyField(to='Jurisdiction') def __str__(self):
return self.name class Meta:
verbose_name = '角色'
verbose_name_plural = '角色' class User(models.Model):
"""用户表"""
name = models.CharField(verbose_name='用户名称', max_length=32)
password = models.CharField(verbose_name='密码', max_length=64)
roles = models.ManyToManyField(to="Role") def __str__(self):
return self.name class Meta:
verbose_name = '用户'
verbose_name_plural = '用户'

models表结构

  - 菜单表;(用于生成二级菜单)

    - 字段:

      - id:

      - title:

      - icon:

  - 用户表;

    - 字段:

      - id:

      - name:

      - pwd:

  - 角色表;

    - 字段:

      - id:

      - name:

  - 权限表;

    - 字段:

      - id:

      - url:

      - name:

      - menu:

  - 用户与角色关联表;

    - 字段:

      - id

      - uid

      - rid

  - 角色与权限关联表;

    - 字段:

      - id

      - rid

      - pid

- 请求访问流程:

  - 中间件:

    - 详情代码:

import re

from django.shortcuts import redirect, HttpResponse
from django.utils.deprecation import MiddlewareMixin from django.conf import settings class RbacMiddleware(MiddlewareMixin):
"""
权限校验的中间件
""" def process_request(self, request):
"""
请求校验
:param request:
:return:
""" # 1. 处理白名单
for ele in settings.VALID_LIST:
if re.match(ele, request.path_info):
return None # 通过白名单,无需再做权限校验 # 2. 权限校验;去session中获取权限然后对用户请求的url 一一进行匹配。
permission_dict = request.session.get(settings.RBAC_PERMISSION_SESSION_KEY)
if not permission_dict:
return redirect('/login/') flag = False
for name, info in permission_dict.items():
reg = "^%s$" % info['url']
if re.match(reg, request.path_info):
flag = True
break
if not flag:
return HttpResponse('无权访问')

中间件代码

    - 进行白名单设置,若访问的是白名单中的URL不做任何限制,例如访问:login/   admin/.* 等等

    - 非白名单中的URL访问的验证;

      - 获取用户浏览器中的session信息,若不存在,则让用户进行登录;

  - login视图:

    - 登录验证:

      - 代码详情:

from django.shortcuts import render, redirect
from rbac import models from crm.utils.md5 import gen_md5
from rbac.service.permission import init_permission def login(request):
"""
用户登录
:param request:
:return:
"""
if request.method == "GET":
return render(request, 'login.html') user = request.POST.get('user')
pwd = request.POST.get('pwd')
pwd_md5 = gen_md5(pwd)
# 根据用户名和密码去数据库校验,是否用户合法。
user_object = models.User.objects.filter(name=user, password=pwd_md5).first() if not user_object:
return render(request, 'login.html', {'msg': '用户名或密码错误'}) # 用户登录成功,获取用户权限信息并放入到session中。
# 初始化session数据
init_permission(user_object, request)
return redirect('/user/')

login视图以及初始化入口

      - 获取form表单信息与数据库进行比较,验证不通过,则返回错误信息;

      - 验证通过,则进行数据初始化,并通过session写入用户浏览器中;

      - 返回重定向;

    - 数据初始化:

      - 根据用户姓名从数据库获取数据,组成相对应的数据结构,写入session;

      - 详情代码:

from django.conf import settings

def init_permission(user, request):
"""
权限初始化
:param user: 用户对象
:param request: 请求相关信息:request.session
:return: 无
"""
# 1. 获取权限信息
# user.roles.all()
permission_queryset = user.roles.filter(permissions__id__isnull=False).values('permissions__id',
'permissions__title',
'permissions__url',
'permissions__name',
'permissions__menu_id',
'permissions__menu__title',
'permissions__menu__icon').distinct()
# 2. 将权限和菜单信息放入到session中。设计:权限和菜单的数据结构。
"""
权限结构 = {
'user':{'url':'/user/'},
'user_add':{'url':'/user/add/'},
...
}
菜单结构 = {
菜单id:{
title:'xxx',
icon:'xx',
children:[
{'title':'xxx','name':'xxx','url':'xxx'} # 能做菜单的权限
]
}
}
生成的两种数据结构:
- permission_dict: 权限认证的字典
- menu_dict:生成二级菜单以及权限控制到按钮级别的字典
"""
permission_dict = {}
menu_dict = {}
for row in permission_queryset:
permission_dict[row["permissions__name"]] = {"url": row["permissions__url"]}
if not row.get("permissions__menu_id"):
continue
if not menu_dict.get(row["permissions__menu_id"]):
menu_dict[row["permissions__menu_id"]] = {
"title": row["permissions__menu__title"],
"icon": row["permissions__menu__icon"],
"children": []
} menu_dict[row["permissions__menu_id"]]["children"].append(
{
"title": row["permissions__title"],
"name": row["permissions__name"],
"url": row["permissions__url"],
}
) # 3. 写入session
request.session[settings.RBAC_PERMISSION_SESSION_KEY] = permission_dict
request.session[settings.RBAC_MENU_SESSION_KEY] = menu_dict

初始化数据结构代码

- 难点:

  - 表关联关系;

- 第一版:
- 根据用户所拥有的权限多少进行限制:
- 需要将用户和权限进行关联:
- 用户表
- 权限表
- 假若用户很多,以及权限很多;
- 生成的关联表中的数据十分多,不利于查询; - 第二版:
- 在第一版的基础上为用户创建角色:
- 让用户表与角色进行关联;
- 角色表与权限表进行关联;
- 通过对不同的角色赋予不同的权限,在通过用户的角色来限制用户的权限;
- 用户与角色需要多对多的关系,生成第三张关联表;
- 介与用户或许会有许多不同的角色身份
- 每个角色都会有许多用户的存在
- 生成第三张 用户与角色关联表; - 同时 权限与角色也是需要多对多的关系:
- 每个权限都有可能会有不同的角色都使用
- 每个角色都有会有不同的多个权限使用;
- 生成第四张 角色与权限关联表 - 补充:菜单表:
- 为了在生成二级菜单时,辅助生成的一张表;
- 详情可见下面的菜单结构的分析

  - 数据结构搭建;

    - 两种数据结构:

权限结构 = {
'user':{'url':'/user/'},
'user_add':{'url':'/user/add/'},
...
}
菜单结构 = {
菜单id:{
title:'xxx',
icon:'xx',
children:[
{'title':'xxx','name':'xxx','url':'xxx'} # 能做菜单的权限
]
}
}

  

    - 权限结构:

      - 在权限结构中,用url的别名作为key,url的路由信息作为value,组成字典;

      - 在中间件中,读取用户携带的该权限字典中所有的values,然后循环判断即可;

      - 若想省事,可以直接组成列表;

    - 菜单结构:

      - 在所有的权限中,可以做菜单的权限不多;例如:添加,删除,更改,便不能作为菜单显示,只能作为按钮显示;

      - 需要在数据库中将可以做菜单,和不可以做菜单的表做出区别;

        - 在这里采取的做法是另外创建一张菜单表,和权限表关联,如果某条权限可以作为菜单,则将该信息和菜单表进行关联,若不可,则为None;

        - 在显示菜单的时候,根据该字段是否有值来进行判断,以便于生成菜单结构字典;

      - 若该菜单id的值存在,且在菜单结构中买有该菜单id的key则新建一个字典,该字典中所对应的 children为空列表。

      - 往所有菜单id相对应的值中的字典中的children对应的列表里添加所有的信息字典;

      - 没有菜单id的权限则continue掉;

- 扩展点:

  - 权限控制到按钮级别;

    - 母板:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<div style="width: 20%;float: left">
{% load rbac %} {% menu request %}
</div> <div style="width: 80%;float: left">
{% block content %} {% endblock %}
</div> </body>
</html>

简单母板

    - filter函数;

from django.template import Library
from django.conf import settings register = Library() @register.filter
def has_permission(name, request):
permission_dict = request.session[settings.RBAC_PERMISSION_SESSION_KEY] if name in permission_dict:
return True

自定义的filter

    - inclusion_tag函数;

# rbac.py

from django.template import Library
from django.conf import settings register = Library() @register.inclusion_tag('menu.html')
def menu(request):
menu_dict = request.session[settings.RBAC_MENU_SESSION_KEY]
return {'menu_dict': menu_dict} ########################### # menu.html
<ul>
{% for menu in menu_dict.values %}
<li>{{ menu.title }}</li>
<ul>
{% for child in menu.children %}
<li><a href="{{ child.url }}">{{ child.title }}</a></li>
{% endfor %}
</ul>
{% endfor %}
</ul>

自定义的inclusion

    - 继承母板以及控制到按钮级别权限的简单示例:

{% extends 'layout.html' %}
{% load rbac %}
{% block content %}
<h1>右侧内容</h1>
{% if 'user_add'|has_permission:request %}
<a href="">添加</a>
{% endif %} <table>
<tbody>
{% for row in data_list %}
<tr>
<td>{{ row.name }}</td>
<td>{{ row.age }}</td>
<td>
{% if 'user_edit'|has_permission:request %}
<a href="">编辑</a>
{% endif %} {% if 'user_del'|has_permission:request %}
<a href="">删除</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table> {% endblock %}

user_list.html

  - js控制菜单hide

  - 分页组件;

  -

项目:rbac 基于角色的权限管理系统;的更多相关文章

  1. RBAC基于角色的权限访问控制

      RBAC是什么,能解决什么难题?ThinkPHP中RBAC实现体系安全拦截器认证管理器访问决策管理运行身份管理器ThinkPHP中RBAC认证流程权限管理的具体实现过程RBAC相关的数据库介绍Th ...

  2. RBAC基于角色的权限管理模型

    一.权限管理模型的必要性: a. 安全性:防止误操作,防止数据泄露,保证信息的安全. b. 数据隔离:保持不同的角色具有不同的权限,只能看到自己权限范围内的数据 二.权限管理模型的发展: a. 传统的 ...

  3. RBAC 基于角色的权限管理的简单实现

    1.什么是权限管理,权限管理就是对后台功能的细分,和对不同工作人员划分不同的工作的管理 RBAC是如何实现的,通过对不同控制器和控制器不同方法的限制,实现的管理. 要实现RBAC需要三张表,一张用户表 ...

  4. RBAC - 基于角色的权限控制

    ThinkPHP中关于RBAC使用详解 自己的源码下载:百度网盘,thinkPHP文件夹下,RBAC文件夹. 重要的是,权限信息的写入函数等.在源码中能找到,Modules/Amin/Common/c ...

  5. SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建

    SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建 技术栈 : SpringBoot + shiro + jpa + freemark ,因为篇幅原因,这里只 ...

  6. 图文详解基于角色的权限控制模型RBAC

    我们开发一个系统,必然面临权限控制的问题,即不同的用户具有不同的访问.操作.数据权限.形成理论的权限控制模型有:自主访问控制(DAC: Discretionary Access Control).强制 ...

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

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

  8. RBAC: K8s基于角色的权限控制

    文章目录 RBAC: K8s基于角色的权限控制 ServiceAccount.Role.RoleBinding Step 1:创建一个ServiceAccount,指定namespace Step 2 ...

  9. ASP.NET MVC 基于角色的权限控制系统的示例教程

    上一次在 .NET MVC 用户权限管理示例教程中讲解了ASP.NET MVC 通过AuthorizeAttribute类的OnAuthorization方法讲解了粗粒度控制权限的方法,接下来讲解基于 ...

随机推荐

  1. LINUX 中 python 版本升级

    首先下载源tar包 可利用linux自带下载工具wget下载,如下所示: 1 # wget http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tg ...

  2. NYIST 1019 G.亲戚来了

    G.亲戚来了 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 Bob 一家人要去下馆子,为什么呢?因为他姑姑的大爷的叔叔的孙子的表叔的婶婶的儿子来了,亲戚来了当然要下 ...

  3. CSDN 轻松周赛赛题:能否被8整除

    轻松周赛赛题:能否被8整除 题目详情 给定一个非负整数,问能否重排它的全部数字,使得重排后的数能被8整除. 输入格式: 多组数据,每组数据是一个非负整数.非负整数的位数不超过10000位. 输出格式 ...

  4. zookeeper 安装笔记 3.6.7

    1 下载 ZK wget  http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.7/zookeeper-3.4.7.tar.gz   2 解 ...

  5. HTML5实战与剖析之媒体元素(3、媒体元素的事件及方法)

    HTML5中的媒体元素除了拥有非常多的属性之外,video标签和audio标签还能够出发非常多事件和方法. 这些方法监控着不同的属性的变化,这些变化有可能是媒体播放的结果,也可能是用户操作媒体的结果. ...

  6. 广东省知名P2P平台资料

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYXNrYmFpNjY2ODg4/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  7. mysql-面试题目1

    一.数据库的ACID 原子性(Atomicity):保证事务中的所有操作全部执行或全部不执行. 一致性(Consistency):保证数据库始终保持数据的一致性——事务操作之前和之后都是一致的. 隔离 ...

  8. Swift学习笔记(二)——常量与变量

    这篇博客将会学习到Swift中的常量Constants和变量Variable.这是学习语言的基础.当中能够看到Swift每句后面基本都是没有:分号的,假设有加:分号的习惯,也能够加上. (1)常量声明 ...

  9. POJ 1012 Joseph(打表题)

    题意:约瑟夫环的变形.要求寻找到一个杀人循环节m使后半节的坏人先被所有杀光. 直接链表模拟出结果,再打表即可: 代码:(凝视的是打表码) #include<iostream> #inclu ...

  10. 基于jquery 的find()函数和children()函数的区别

    element.find(selector)  返回匹配element集合中每个元素的后代,参数selector是必须的,可以通过选择器对元素进行过滤,筛选出符合条件的元素.如果想选中所有的后代元素, ...