role-based access control(rbac),指对于不同角色的用户,拥有不同的权限 。用户对应一个角色,一个角色拥有若干权限,形成用户-角色-权限的关系,如下图所示。当一个用户进行访问数据时,根据其角色判断其拥有的权限,限定其操作。通过django实现一个简单的rbac app,简要记录下过程。

1.实现效果

  实现效果如下图所示,不同用户拥有不同角色,不同角色拥有不同权限。下图中只是对角色和用户两张表进行编辑和访问,当我们项目中还有其他数据需要进行权限控制访问时,只需进行两处设置,一是在权限表中为这个数据表增加 "增删改查" 四个权限,然后将对应权限添加到角色表中即可。

2. 实现过程

  2.1 数据库设计

    建立四张表,用户表,角色表,权限表和权限组表。models.py代码如下:

from __future__ import unicode_literals
from django.db import models class User(models.Model):
name = models.CharField(max_length=32)
password = models.CharField(max_length=16)
age = models.IntegerField()
role = models.ForeignKey(to='Role')
def __str__(self):
return self.name class Role(models.Model):
title = models.CharField(max_length=32)
permission = models.ManyToManyField(to='Permission')
def __str__(self):
return self.title class Permission(models.Model):
title = models.CharField(max_length=32)
url = models.CharField(max_length=32)
action = models.CharField(max_length=32)
group = models.ForeignKey(to='PermissionGroup')
def __str__(self):
return self.title class PermissionGroup(models.Model):
title = models.CharField(max_length=32)
def __str__(self):
return self.title

models.py

    这里一条权限实际上对应一条url,表示对一张数据表的一个操作(增删改查),而权限分组则表明权限属于对那张表的操作。因此有几张可以操作的数据表应对应几个权限组,而每个权限组,应该都包括四个权限:增删改查。一条权限的数据信息如下图。这里只有用户表和角色表两张表可以操作,对应用户管理和角色管理两个权限组。

  2.2 权限控制

    用户是通过url来访问数据,而一条url对应一个权限。因此当用户访问数据时,权限控制的流程是:
      a, 首先判断用户是否登录,未登录时重定向至登陆页面。

      b,用户登陆进来时,根据其角色判断拥有的所有权限,并将其权限表计入session中。

      c,用户登陆后,当其访问数据时,根据session中权限表判断,若无查看权限则直接拒绝,否则允许查看,进一步判断增删改权限来个性化前端显示页面。

    url代码如下:

# 总的一级路由 
from django.conf.urls import url,include
from django.contrib import admin urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'',include('rbac.urls'))
] # rbac.urls代码,二级分发路由
urlpatterns = [
   url(r'^login/$', views.login),
url(r'^user/$', views.listUser),
url(r'^user/add/', views.addUser),
url(r'^user/edit/(\d+)', views.editUser),
url(r'^user/delete/(\d+)', views.deleteUser),
url(r'^role/$', views.listRole),
url(r'^role/add/', views.addRole),
url(r'^role/edit/(\d+)', views.editRole),
url(r'^role/delete/(\d+)', views.deleteRole), ]

  url权限的判断,通过自定义中间件来实现,将用户访问的url和其权限表url匹配,拥有权限时才允许通过,交给相应的视图函数处理。代码如下:

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,redirect
import re
#自定义中间件
class ValidPermission(MiddlewareMixin):
def process_request(self,request):
current_path = request.path # 拿到当前请求路径 '/user/'

     #设置白名单,允许任何人访问的url
valid_urls = ['/login/','/admin/(.*)']
for url in valid_urls:
path = '^%s$'%url
ret = re.match(path, current_path)
if ret:
return None #对于没有登陆的用户重定向至登陆页面
user_id = request.session.get('user',[])
if not user_id:
return redirect('/login/') #根据权限来匹配url,决定当前用户是否有访问权限
permission_list = request.session['permission_list']
# print permission_list,current_path
for permission in permission_list.values():
urls = permission['permission__url']
for url in urls:
path = '^%s$'%url
ret = re.match(path,current_path)
if ret:
request.actions = permission['permission__action'] #[u'list', u'edit', u'add']
# print request.actions
return None
return HttpResponse('没有访问权限')

  登陆函数代码:

def login(request):
if request.method=='POST':
name = request.POST.get('name')
passsword = request.POST.get('password')
# print name, passsword
user_obj = models.User.objects.filter(name=name,password=passsword).first()
if user_obj:
request.session['user']=user_obj.pk
initial_permission(request,user_obj)
return redirect('/user/')
else:
return render(request,'login.html')
return render(request, 'login.html') from rbac import models
def initial_permission(request,user):
permissions = models.Role.objects.filter(user=user).values('permission__url','permission__action','permission__group_id').distinct()
permission_list = {}
for item in permissions:
if item['permission__group_id'] not in permission_list:
permission_list[item['permission__group_id']]= {'permission__url':[item['permission__url'],],'permission__action':[item['permission__action'],]}
else:
permission_list[item['permission__group_id']]['permission__url'].append(item['permission__url'])
permission_list[item['permission__group_id']]['permission__action'].append(item['permission__action'])
#print permission_list
request.session['permission_list'] = permission_list
# 按用户组权限id分组,得到如下的数据结构,即对两张表分别的操作权限
# {1: {'permission__url': [u'/user/', u'/user/edit/(\\d+)', u'/user/add/'],
# 'permission__action': [u'list', u'edit', u'add']},
# 2: {'permission__url': [u'/role/'], 'permission__action': [u'list']}} #设置菜单的显示权限数据
menu_permissions = models.Role.objects.filter(user=user).values('permission__url','permission__action','permission__group__title').distinct()
menu_permission_list=[]
for item in menu_permissions:
if item['permission__action'] == 'list': menu_permission_list.append((item['permission__url'],item['permission__group__title']))
request.session['menu_permission_list'] = menu_permission_list
# print menu_permission_list

  视图函数的处理主要时将数据和用户权限传给前端,前端根据权限来显示不同的页面(若用户拥有添加,删除,编辑权限,则显示增加,删除,编辑按钮,否则不显示),下面是查看用户表的视图函数和前端页面:

class PermissionAction(object):
def __init__(self,actions):
self.actions = actions
def add_check(self):
return 'add' in self.actions
def edit_check(self):
return 'edit' in self.actions
def delete_check(self):
return 'delete' in self.actions
# 查看用户表的视图函数
def listUser(request):
users = models.User.objects.all()
user_id = request.session.get('user')
user = models.User.objects.filter(id=user_id).first()
permission_action = PermissionAction(request.actions)
return render(request, 'rbac/listUser.html', locals())

listUser.html

{% extends 'rbac/base.html' %}
{% block data_table %}
<div>
{% if permission_action.add_check %}
<a href="/user/add/">
<button class="btn btn-success" style="margin-bottom: 15px">添加用户</button>
</a>
{% endif %}
</div>
<table class="table table-bordered ">
<thead>
<tr>
<th>用户名</th>
<th>角色</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ user.name }}</td>
<td>{{ user.role }}</td>
<td>
{% if permission_action.edit_check %}
<a href="/user/edit/{{ user.pk }}">
<button class="btn btn-success">编辑</button>
</a>
{% endif %}
{% if permission_action.delete_check %}
<a href="/user/delete/{{ user.pk }}">
<button class="btn btn-danger" style="margin-left:15px">删除</button>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

完整代码见github:https://github.com/silence-cho/Rbac

基于角色的权限控制系统(role-based access control)的更多相关文章

  1. Azure ARM (16) 基于角色的访问控制 (Role Based Access Control, RBAC) - 使用默认的Role

    <Windows Azure Platform 系列文章目录> 今天上午刚刚和客户沟通过,趁热打铁写一篇Blog. 熟悉Microsoft Azure平台的读者都知道,在老的Classic ...

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

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

  3. ASP.net MVC 基于角色的权限控制系统的实现

    一.引言 我们都知道ASP.net mvc权限控制都是实现AuthorizeAttribute类的OnAuthorization方法. 下面是最常见的实现方式: public class Custom ...

  4. Azure ARM (17) 基于角色的访问控制 (Role Based Access Control, RBAC) - 自定义Role

    <Windows Azure Platform 系列文章目录> 在上面一篇博客中,笔者介绍了如何在RBAC里面,设置默认的Role. 这里笔者将介绍如何使用自定的Role. 主要内容有: ...

  5. [认证授权] 6.Permission Based Access Control

    在前面5篇博客中介绍了OAuth2和OIDC(OpenId Connect),其作用是授权和认证.那么当我们得到OAuth2的Access Token或者OIDC的Id Token之后,我们的资源服务 ...

  6. RABC(Role-Based Access Control) 基于角色的权限访问控制

    基于角色的权限访问控制(Role-Based Access Control),通过角色绑定权限,然后给用户划分角色.在web应用中,可以将权限理解为url,一个权限对应一个url. 使用thinkph ...

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

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

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

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

  9. webapi框架搭建-安全机制(四)-可配置的基于角色的权限控制

    webapi框架搭建系列博客 在上一篇的webapi框架搭建-安全机制(三)-简单的基于角色的权限控制,某个角色拥有哪些接口的权限是用硬编码的方式写在接口上的,如RBAuthorize(Roles = ...

随机推荐

  1. ES6模块化及优点,简单案例让你秒懂

    模块化:模块是一个文件     好处:         1.减少命名冲突         2.避免引入时的层层依赖         3.可以提升执行效率     **第一种方法************ ...

  2. Python: NumPy, Pandas学习资料

    NumPy 学习资料 书籍 NumPy Cookbook_[Idris2012] NumPy Beginner's Guide,3rd_[Idris2015] Python数据分析基础教程:NumPy ...

  3. 第三章、前端之JavaScript

    目录 第三章.前端之JavaScript 一.javaScript的引入方式 二.JavaScript语言的规范 三.语言基础 变量声明 四.数据类型 五.流程控制 六.函数 函数的argument ...

  4. 从0到1写rtos:事件的控制块与通知

    任务的状态: 未创建:只定义了任务代码,未调用tTaskInit()初始化 就绪:任务已经创建完毕,且等待机会占用CPU运行 运行:任务正在占用CPU运行代码 延时:任务调用tTaskDelay()延 ...

  5. 区块链火爆,再不知道Golang就晚了

    Golang,也叫Go语言,是2009年刚刚被发发布的一门新语言. 区块链,是2019年我国提出的新战略. 一个不争的事实就是,大多数从事区块链开发的小伙伴都是用Golang,大多数招聘区块链技术工作 ...

  6. Tensorflow目录

    0.Tensorflow安装 1.创建会话,启动会话 2.变量 3.Fech_feed 4.线性回归 5.非线性回归 6.MNIST数据集简单分类 7.交叉熵 8.Dropout 9.正则化 10.优 ...

  7. D. Connected Components Croc Champ 2013 - Round 1 (并查集+技巧)

    292D - Connected Components D. Connected Components time limit per test 2 seconds memory limit per t ...

  8. Pycharm建立web2py项目

    web2py是一种免费的,开源的web开发框架,用于敏捷地开发安全的,数据库驱动的web应用:web2p采用Python语言编写,并且可以使用Python编程.web2py是一个完整的堆栈框架,也就是 ...

  9. fonts/font-awesome-woff2 404问题

    报错环境: vue 开发的项目 npm 引入的font-awesome, 页面正常显示,就是控制台会报这个错误 产生原因:因为服务器IIS不认SVG,WOFF/WOFF2 这几个文件类型,只要在IIS ...

  10. CSS基础学习 21.CSS居中总结

    注意:*在IE中并不代表通配符的意思,是代表根元素的意思,所以为了匹配适应各种浏览器,进行页面初始化 <style> *{ margin:0; padding:0; } </styl ...