- 简单示意流程图

- 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. nginx index.html

    [root@web03 nginx]# ls -l|grep -v temptotal 36drwxr-xr-x 2 root root 4096 Jun 7 15:36 confdrwxr-xr-x ...

  2. Hibernate简单的保存操作

    1.这里面我想先说一下session对象的创建,这个是我们操纵数据库的核心对象,因此首先我们应该获取相应的session对象. public static Configuration cfg; pub ...

  3. const int *a与int *const a,const int *const a的区别

    来源:https://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰 ...

  4. 【codeforces 553C】Love Triangles

    [题目链接]:http://codeforces.com/problemset/problem/553/C [题意] 给你n个点,m条边; 每种边有2两种类型; 让你补充剩下的边,构造一个完全图; 使 ...

  5. 在oracle中采用connect by prior来实现递归查询

    注明:该文章为引用别人的文章,链接为:http://blog.csdn.net/apicescn/article/details/1510922 , 记录下来只是为了方便查看 原文: connect ...

  6. google在线測试练习题3

    Problem The Latin alphabet contains 26 characters and telephones only have ten digits on the keypad. ...

  7. Caused by: java.lang.ClassNotFoundException: com.njupt.libgdxbase.MainActivity

    在使用libgdx来开发游戏时.假设遇到这样的问题.非常可能是由于你没有在libgdx的项目中导入Android的现骨干jar包导致的. 解决方法例如以下: 右击项目---"build pa ...

  8. Import Example Dataset

    Overview The examples in this guide use the restaurants collection in the test database. The followi ...

  9. 区间dp学习笔记

    怎么办,膜你赛要挂惨了,下午我还在学区间\(dp\)! 不管怎么样,计划不能打乱\(4\)不\(4\).. 区间dp 模板 为啥我一开始就先弄模板呢?因为这东西看模板就能看懂... for(int i ...

  10. JavaScript中函数作为另一个函数的参数的时候它存在于哪个作用域

    一直对函数作为参数被传递进另外一个函数理解的不是很清除.先看下这段代码吧: function test(fn){ var bar = 1; fn(); } var bar = 99; test(fun ...