基于中间件的RBAC权限控制
RBAC 是什么
RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。
在 Django 中,权限就是用户对一个包含正则表达式 url 有没有访问的权利。
RBAC 的实现
在编写程序过程中,要注重弱耦合,所以在创建项目之初,应当将 RBAC 功能和逻辑功能分开来,创建不同的应用。
表
基于 RBAC 的权限管理最根本上需要对数据表进行更改。实现该方法需要五张表,用户表,角色表,权限表,用户与角色关系表,角色与权限关系表。
关于数据表的代码如下。
class User(models.Model):
name=models.CharField(max_length=32)
pwd=models.CharField(max_length=32)
roles=models.ManyToManyField(to="Role")
def __str__(self): return self.name
class Role(models.Model):
title=models.CharField(max_length=32)
permissions=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)
def __str__(self):return self.title
登录校验
对用户进行校验的前提是用户登录,并且用户登录信息浏览器要在其他页面当中依然能够取得,所以将用户 ID 存入 session 中。
在用户登录时除了存储用户 ID 信息外,还应存储用户的所有权限信息。
登录视图函数:
from django.shortcuts import render, HttpResponse
from rbac import models
import re
from rbac.service.permission import *
# Create your views here.
def login(request):
if request.method == "POST":
username = request.POST["username"]
pwd = request.POST["pwd"]
user_obj = models.User.objects.filter(name=username, pwd=pwd).first()
# 登录用户存在
if user_obj:
# 将用户ID存入session
request.session["user_id"] = user_obj.pk
# 查询当前登录用户的所有权限,注册到session中
initial_session(user_obj, request)
return HttpResponse("登录成功!")
return render(request, "login.html")
查询并注册用户权限信息到 session 的代码如下:
# /rbac/service/permission.py
def initial_session(user, request):
# 将用户权限列表存入session
# 取出登录用户的权限url并去重
# permissions = models.Role.objects.filter(user=user_obj).values("permissions__url").distinct()
permissions = user.roles.all().values("permissions__url").distinct()
permission_list = []
for item in permissions:
permission_list.append(item["permissions__url"])
request.session["permission_list"] = permission_list
在 session 中存储了用户 ID 信息后判断是否登录就很方便了:
# 校验是否登录
if not request.session.get("user_id"):
return redirect('/login/')
校验权限
前文中已经提到过,权限就是带正则表达式的 url ,对权限进行校验就是看当前 url 路径是否在用户权限列表中,如果在则用户有访问该 url 的权限。
其中,在判断当前路径是否在权限列表中时应该使用正则匹配并注意要完全匹配,不能简单的使用
元素 in 列表 这种简单判断。
# 当前路径
current_path = request.path_info
# 校验权限
flag = False
permission_list = request.session.get("permission_list", [])
for permission in permission_list:
# 保障url完全匹配
permission = "^%s$" % permission
ret = re.match(permission, current_path)
if ret:
flag = True
break
if not flag:
return HttpResponse("没有权限访问")
加入中间件
有了实现权限校验的代码之后,如果想要在各个 url 中都进行校验就需要在每个相应的视图函数中填上相应的代码,造成了代码冗余。
既然每个视图函数都需要进行校验,最好的办法就是使用中间件,项目启动后每次访问 url 都会自动走该中间件,从而进行了权限校验。
有关中间件的知识请参考:Django 中的中间件
使用中间件会发生一个问题:有些不需要校验的 url ,比如登录链接,注册链接,后台管理链接也都会进行校验从而报错,因此,需要对 url 设置一个白名单。
# 校验是否为白名单
valid_url_list = ["/login/", "/reg/", "/admin/.*"]
for item in valid_url_list:
ret = re.match(item, current_path)
if ret:
return None
中间件的完整代码:
# /rbac/service/rbac.py
from django.utils.deprecation import MiddlewareMixin
import re
from django.shortcuts import HttpResponse, redirect
class ValidPermissionMiddleware(MiddlewareMixin):
def process_request(self, request):
# 当前路径
current_path = request.path_info
# 校验是否为白名单
valid_url_list = ["/login/", "/reg/", "/admin/.*"]
for item in valid_url_list:
ret = re.match(item, current_path)
if ret:
return None
# 校验是否登录
if not request.session.get("user_id"):
return redirect('/login/')
# 校验权限
flag = False
permission_list = request.session.get("permission_list", [])
for permission in permission_list:
# 保障url完全匹配
permission = "^%s$" % permission
ret = re.match(permission, current_path)
if ret:
flag = True
break
if not flag:
return HttpResponse("没有权限访问")
return None
GitHub 地址:https://github.com/protea-ban/oldboy/tree/master/9day82/rbacDemo

基于中间件的RBAC权限控制的更多相关文章
- 基于SpringSecurity实现RBAC权限控制(待完善)
Spring Security是一个为企业应用系统提供声明式的安全访问控制功能,减少为了企业应用系统安全控制而编写的大量重复代码. 认证: spring security的原理就是使用很多的拦截器对U ...
- 基于thinkphp的RBAC权限控制
RBAC Role-Based Access Control 权限控制在后台管理中是十分常见的,它的模型大体上是下面这张图的形式 我用的字段和上面不一样,图只是个示例 一个简易的权限控制模型只需要3 ...
- python RBAC权限控制模型扩展 基于JWT实现
jwt,全称 json web token,是使用一定的加密规则生成的token串来保证登录状态.验证用户身份.做权限认证等工作 以往保存用户登录状态多用session实现,但是当服务涉及多台服务器分 ...
- vue基于d2-admin的RBAC权限管理解决方案
前两篇关于vue权限路由文章的填坑,说了一堆理论,是时候操作一波了. vue权限路由实现方式总结 vue权限路由实现方式总结二 选择d2-admin是因为element-ui的相关开源项目里,d2-a ...
- yii2搭建完美后台并实现rbac权限控制实例教程
1.安装yii2 未安装的请参考yii2史上最简单式安装教程,没有之一 或者参考yii2实战教程之详细安装步骤 已安装的请继续看下一步操作 2.配置数据库 2.1 配置数据库 修改common/con ...
- Kubernetes-16:一文详解ServiceAccount及RBAC权限控制
一.ServiceAccount 1.ServiceAccount 介绍 首先Kubernetes中账户区分为:User Accounts(用户账户) 和 Service Accounts(服务账户) ...
- yii2 rbac权限控制详细操作步骤
作者:白狼 出处:http://www.manks.top/article/yii2_rbac_description本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 ...
- yii2 rbac权限控制之菜单menu详细教程
作者:白狼 出处:http://www.manks.top/article/yii2_rbac_menu本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...
- Struts2中基于Annotation的细粒度权限控制
Struts2中基于Annotation的细粒度权限控制 2009-10-19 14:25:53| 分类: Struts2 | 标签: |字号大中小 订阅 权限控制是保护系统安全运行很重要 ...
随机推荐
- 分布式基础学习【二】 —— 分布式计算系统(Map/Reduce)
二. 分布式计算(Map/Reduce) 分布式式计算,同样是一个宽泛的概念,在这里,它狭义的指代,按Google Map/Reduce框架所设计的分布式框架.在Hadoop中,分布式文件系统,很大程 ...
- mysql 基本操作 alter
查看数据库 show databases; 新建数据库 命令 create database 库名字. 选择数据库 use 2016test; 创建表:create table 表名(字段1,2, ...
- Docker学习之路(三)Docker网络详解
1. Docker的4种网络模式 我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下4种网络模式: host模式,使用--net=host ...
- TTS技术
一.简介 TTS技术,TTS是Text To Speech的缩写,即"从文本到语音".它将计算机自己产生的.或外部输入的文字信息转变为可以听得懂的.流利的汉语口语(或者其他语言语音 ...
- Luogu 4784 [BalticOI 2016 Day2]城市
斯坦纳树复习,我暑假的时候好像写过[JLOI2015]管道连接来着. 设$f_{i, s}$表示以$i$为根,$k$个重要点的连通状态为$s$,($0$代表没有连进最小生成树里面去,$1$代表连进了最 ...
- 数据结构 Merge合并排序
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 4、MemorySubSystem
1.概述 S3C6410X存储器子系统包括7个存储器控制器,SROM控制器,两个OneNAND控制器,一个NAND Flash控制器,一个CF控制器,一个DRAM控制器.静态存储器控制器,oneNAN ...
- Python基础入门-数据类型
一.变量 1)变量定义 在python中,我们可以把变量理解为一个值,变量是一个标签名,变量是有对应的一个值. name = 100(name是变量名 = 号是赋值号100是变量的值) 2)变量赋值 ...
- GTA4下载和玩教程
侠盗猎车4中文版.rar: 但是下载安装之后总是在刚开始开车的时候跳转到人物界面卡在那里无法进行下去,解决办法: 1.新建一个commandline.txt文件复制以下内容进去 -novblank - ...
- tomcat的内存配置,关于-Xms -Xmx -XX:PermSize -XX:MaxPermSize的理解和区别
JVM按照其存储数据的内容将所需内存分配为堆区与非堆区两个部分:所谓堆区即为通过new的方式创建的对象(类实例)所占用的内存空间:非堆区即为代码.常量.外部访问(如文件访问流所占资源)等.然而虽然ja ...