rbac: Role_Based Access Control,基于角色的权限控制

权限:一个包含正则表达式 的url就是一个权限

目录结构:

rbac这个app中的文件代码如下:

rbac/models.py

from django.db import models

# Create your models here.

class User(models.Model):
   # 这个User要和 app 中的 用户信息表 一对一关联; from rbac.models import *
name = 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=128)
actions = models.CharField(max_length=32) # 用于标识“增删改查”某一操作 --- "add","delete","edit","list"
group = models.ForeignKey(to="PermissionGroup",on_delete=models.CASCADE) # 能够避免页面渲染时,判断 <a>标签是否存在时的 url 带有表名 """
所要得到的数据结构 permission_dict :
{
1:{
url:[...],
actions:[...]
}
2:{
url:[...],
actions:[...]
},
...
}
# 字典中的数字键代表 permission_group,即权限分类(角色或者表名分类)
""" def __str__(self):
return self.title class PermissionGroup(models.Model):
"""
作用:标识哪个权限属于哪个组(或者说是哪个表的增删改查)
"""
title = models.CharField(max_length=32) def __str__(self):
return self.title

rbac/service/register_permissions.py

def initiate_permissions_session(request,user):
""" 登陆后把权限注册到session中 """ # 方式一:只包含 url 的列表
"""
permissions = user.roles.all().values("permissions__url").distinct() # 取出当前用户的所有权限(QuerySet;要去重) permission_list = []
for item in permissions:
permission_list.append(item["permissions__url"]) request.session["permission_list"] = permission_list # 把权限列表注册到session 中,以后直接从 session 中去取
""" # 方式二:字典
permissions = user.roles.all().values("permissions__url","permissions__actions","permissions__group_id").distinct() permissions_dict = {}
for item in permissions:
pgid = item.get("permissions__group_id")
if pgid not in permissions_dict:
permissions_dict[pgid] = {
"actions":[item["permissions__actions"]],
"urls":[item["permissions__url"]]
}
else:
permissions_dict[pgid]["actions"].append(item["permissions__actions"])
permissions_dict[pgid]["urls"].append(item["permissions__url"]) request.session["permissions_dict"] = permissions_dict """
方式二得到的 permissions_dict 数据结构形式:
{
1:{
url:[...],
actions:[...]
}
2:{
url:[...],
actions:[...]
},
...
}
""" """
登陆验证成功后要调用这个函数
"""

rbac/service/rbac.py

from django.utils.deprecation import MiddlewareMixin
import re
from django.shortcuts import redirect,HttpResponse class PermissionValid(MiddlewareMixin):
"""
通过中间件校验用户是否有权限访问某个url
""" def process_request(self,request): current_path = request.path url_white_list = ["/login/","/reg/","/admin/.*"] # /admin/.*" 表示 所有 以 admin 开关的url # 先校验当前的 url 是否在 白名单中 (url_white_list中有正则,不能直接用 in 判断)
for url in url_white_list:
ret = re.match(url,current_path)
if ret:
return None # 通过校验 # 再校验当前用户是否已经登陆(根据具体的登陆验证逻辑来重构这块的代码)
if request.user.is_anonymous:
return redirect("/login/") # 跳转到登陆页面 """
def reg(request,current_path):
permission_list = request.session.get("permission_list", [])
flag = False
for permission in permission_list: permission = "^%s$" % permission ret = re.match(permission, current_path)
if ret:
flag = True
break
return flag #校验权限1(permission_list)
permission_list = request.session.get("permission_list",[]) # ['/users/', '/users/add', '/users/delete/(\\d+)', 'users/edit/(\\d+)']
flag=reg(request,current_path) if not flag:
return HttpResponse("没有访问权限!") return None
""" # 校验权限2:(permission_dict) 最后判断用户是否有当前url 的权限
permissions_dict = request.session["permissions_dict"]
for item in permissions_dict.values():
for url in item["urls"]:
ret = "^%s$"%url # 为了让 url 和 current_path 完全匹配,需要在其前后加上 ^$
ret = re.match(url,current_path)
if ret:
request.actions = item["actions"] # 如果匹配成功,就把该当前用户对该表的所有能进行的操作添加到 request中; # Permission表中 actions & group字段,和 PermissionGroup这个表都是为了这一步
return None
return HttpResponse("您没有这个url的权限!")

rbac组件小结:

 权限粒度控制

     简单控制:
{% if "users/add" in permissions_list%} 摆脱表控制 更改数据库结构
class Permission(models.Model):
title=models.CharField(max_length=32)
url=models.CharField(max_length=32) action=models.CharField(max_length=32,default="")
group=models.ForeignKey("PermissionGroup",default=1)
def __str__(self):return self.title class PermissionGroup(models.Model):
title = models.CharField(max_length=32) def __str__(self): return self.title 登录验证:
permissions = user.roles.all().values("permissions__url","permissions__group_id","permissions__action").distinct() 构建permission_dict permissions:
[ {'permissions__url': '/users/add/',
'permissions__group_id': 1,
'permissions__action': 'add'}, {'permissions__url': '/roles/',
'permissions__group_id': 2,
'permissions__action': 'list'}, {'permissions__url': '/users/delete/(\\d+)',
'permissions__group_id': 1,
'permissions__action': 'delete'}, {'permissions__url': 'users/edit/(\\d+)',
'permissions__group_id': 1,
'permissions__action': 'edit'}
] permission_dict { 1: {
'urls': ['/users/', '/users/add/', '/users/delete/(\\d+)', 'users/edit/(\\d+)'],
'actions': ['list', 'add', 'delete', 'edit']}, 2: {
'urls': ['/roles/'],
'actions': ['list']} } 中间价校验权限:
permission_dict=request.session.get("permission_dict") for item in permission_dict.values():
urls=item['urls']
for reg in urls:
reg="^%s$"%reg
ret=re.match(reg,current_path)
if ret:
print("actions",item['actions'])
request.actions=item['actions']
return None return HttpResponse("没有访问权限!")

最新文章

  1. PHP新手常见的一些不好习惯(抄的 有待理解)
  2. ZOJ Problem Set - 1078 Palindrom Numbers
  3. docker&#39;部署
  4. [算法][LeetCode]Linked List Cycle &amp; Linked List Cycle II——单链表中的环
  5. HackRF实现ADS-B飞机信号跟踪定位
  6. awk中文手册
  7. 设计模式_Adapt
  8. shell脚本练习(autocert)
  9. AndroidUI组件之ListView小技巧
  10. SpannableString可以被点击的文字
  11. DailyTick 开发实录 —— UI 设计
  12. 使用git工具将项目上传到github
  13. 五分钟学习React(四):什么是JSX
  14. Typora - Markdown 语法说明
  15. cdnbest如何在站点里开启强制缓存
  16. wampserver 的默认首页设置
  17. ssh采用expect实现自动输入密码登录、拷贝
  18. Centos7部署kubernetes准备工作(一)
  19. 07.linux系统管理命令
  20. 【LeetCode题解】225_用队列实现栈(Implement-Stack-using-Queues)

热门文章

  1. log4js日志配置问题
  2. SpringCloud开发学习总结(一)—— 基础知识
  3. TabLayout+ViewPager实现标签卡效果
  4. 洛谷 P1339 [USACO09OCT]热浪Heat Wave (堆优化dijkstra)
  5. 微信小程序---账号注册与开发工具
  6. 【东软实训】SQL多表链接
  7. python 删除/查找重复项
  8. P2P实现的原理
  9. cc.Button
  10. 简单说一下Set,list,Map的类型和自己的特点