RBAC 升级版

预期要求

  前端在无权限时不在提供操作标签

  更改部分硬编码

  实现更加精准的权限控制

未改动前的版本

在这里 ⬇

Django_rbac_demo 权限控制组件框架模型

具体更改

数据库结构更改:

  对 permission 表新增两个字段 用于分类具体控制表(group)  以及当前操作行为 (action)

  增加新表 permissiongroup 用来保存控制表字段

models.py 

from django.db import models

# Create your models here.

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)
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

permission.py

   表结构更改后,后台可利用的数据更多。传回一个字典。

   以及需要 数据处理成便于操作的形式

"""
为了解耦,将处理权限的代码保存在组件里面
""" def initial_session(user,request): """
方案1
不好用,只用一个权限字段实在功能有限
     已被淘汰
""" # # 查看当前用户的所有的权限
# # 因为会有values 的原理会导致有重复需要去重
# ret = user.roles.all().values("permissions__url").distinct()
# permission_list = []
# # 将所有的权限保存在一个列表里面,稍微处理下数据便于操作
# for i in ret:
# permission_list.append(i["permissions__url"])
# # 把用户的用户权限保存在 session 里面
# request.session["permission_list"] = permission_list """
方案2
"""
# permission__group_id permission表 的group 字段 因为外键会后面加个 ”_id“ 别忘了啊
# 取出来当前用户的权限,每个权限对应的属性
permissions = user.roles.all().values(
"permissions__url",
"permissions__group_id",
"permissions__action",).distinct()
# 对拿到的数据进行数据处理
permission_dict = {}
for i in permissions:
gid = i["permissions__group_id"]
if gid not in permission_dict:
permission_dict[gid] = {
"urls": [i["permissions__url"], ],
"actions": [i["permissions__action"], ]
}
else:
permission_dict[gid]["urls"].append(i["permissions__url"])
permission_dict[gid]["actions"].append(i["permissions__action"])
request.session["permission_dict"] = permission_dict

rbac.py 

  对传回的数据进行权限验证

import re
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect """
写在中间件里面可以完全避免每次都要重复校验的问题
在请求来的时候进行校验,因此要写在 process_request 方法里面
""" class ValidPermission(MiddlewareMixin):
def process_request(self, request):
# 当前访问路径
current_path = request.path_info
"""
检查是否属于白名单
admin 的内部流程
不允许一上来就访问首页,必须要跳转到 登陆页面
http://127.0.0.1:8000/admin/login/?next=/admin/
第二次跳转到登录页面的请求如果没有被定义可通过就会被拦截
无法只使用 admin 为过滤选项
不能用 in 单纯的判断,还是要用到正则处理
需要放过所有 admin 开头的 url
"""
valid_url_list = ["/login/", "/reg/", "/admin/.*"]
for valid_url in valid_url_list:
ret = re.match(valid_url, current_path)
if ret:
# 中间件 return None 表示这个中间件已经执行完毕
return None """
校验是否登录
对于没有登陆的用户返回报错应该是让他去登陆
"""
user_id = request.session.get("user_id")
if not user_id:
return redirect("/login/") # """
# 校验权限 1 permission_list
# 在编辑,以及删除页面的时候 url 不是固定的,
# 会有内含的参数,因此权限列表里面不能仅仅是写死的url
# 也不能再单纯的用 in 来判断。还是要靠正则来处理
# 将权限列表里面的权限信息用 正则表达式来保存
# 然后对访问页面进行验证是否可以通过来处理
# """
# 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
# if not flag:
# return HttpResponse("没有访问权限!")
# return None """
校验权限 2 permission_dict
"""
permission_dict = request.session.get("permission_dict")
for i in permission_dict.values():
urls = i["urls"]
for reg in urls:
reg = f"^{reg}$"
ret = re.match(reg, current_path)
if ret:
# 加一个自定义的 actions 属性在里面
request.actions = i["actions"]
return None
return HttpResponse("没有访问权限!")

views.py

   封装一个 Per 类便于前端更方便的取数据

from django.shortcuts import render,HttpResponse
import re
# Create your views here.
from rbac.models import *
from rbac.service.perssions import * class Per():
def __init__(self,actions):
self.actions = actions def add(self):
return "add" in self.actions def delete(self):
return "del" in self.actions def edit(self):
return "edit" in self.actions def cat(self):
return "cat" in self.actions
def users(request):
user_list = User.objects.all()
# permission_dict = request.session["permission_dict"]
# 查询当前登陆人的名字
id = request.session.get("user_id")
user = User.objects.filter(id=id).first()
per = Per(request.actions)
return render(request, "users.html",locals()) def add_user(request):
permission_list = request.session["permission_list"]
return HttpResponse("add user.....") def del_user(request,id):
return HttpResponse(f"del_user: {id}") def roles(request):
role_list = Role.objects.all()
per = Per(request.actions)
return render(request,"roles.html",locals()) def login(request):
print("login")
if request.method == "POST":
user = request.POST.get("user")
pwd = request.POST.get("pwd")
# 拿到当前用户对象
user = User.objects.filter(name=user, pwd=pwd).first()
if user:
# 把用户的id 保存在 session 里面
request.session["user_id"] = user.pk
# 查询当前用户的所有的权限
initial_session(user, request)
return HttpResponse("登录成功!")
return render(request, "login.html",locals())

 users.html 

   前端页面基于 per 对象的 actions 控制才判断是否对标签进行显示

{% extends "base.html" %}
{% block con %}
<h4>用户列表</h4> {% if per.add %}
<a href="/users/add/" class="btn btn-primary">添加用户</a>
{% endif %}
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>角色</th>
<th>操作</th>
</tr>
</thead> <tbody>
{% for user in user_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ user.name }}</td>
<td>
{% for role in user.roles.all %}
{{ role.title }}
{% endfor %}
</td>
<td>
{% if per.delete%}
<a href="/users/delete/{{ user.pk }}/" class="btn btn-danger">删除</a>

{% endif %}
{% if per.edit %}
<a href="" class="btn btn-warning">编辑</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

Django_RBAC_demo2 升级版权限控制组件的更多相关文章

  1. 基于.netstandard的权限控制组件

    基于.netstandard的权限控制组件 Intro 由于项目需要,需要在 基于 Asp.net mvc 的 Web 项目框架中做权限的控制,于是才有了这个权限控制组件. 项目基于 .NETStan ...

  2. Django_rbac_demo 权限控制组件框架模型

    rbac 权限控制组件 基于角色的权限控制 本质每个权限即为一个 URL 项目组件结构 表结构 Role (title, permission) -(ManyToManyField)-   User  ...

  3. rbac权限控制组件实现控制的基本原理图

    今天先整理一个rbac的权限控制的原理图上来 代码 后面就不透漏了,但是实现的方法有很多种,我这个只是其中一种的一部分!

  4. Python 目录指引

    1.0 Python 基础整合 1.1 变量 1.2 数据类型 1.3 基础语法 1.4 文件操作 1.5 函数 1.6 生成器 1.7 迭代器 1.8 装饰器 1.9 字符集 2.0 Python ...

  5. 仿SiteMap实现Asp.net 网站的菜单和权限管理

    在Asp.net中,SiteMap用于站点导航,可以与Menu等控件一起使用实现网站的菜单和权限管理.但是SiteMap提供的方法都是只读的,无法再运行时修改(菜单)导航文件,需要手动修改配置web. ...

  6. 实现对ASP.NETMvc及Asp.NetCore的权限控制

    AccessControlHelper Build Status Intro 由于项目需要,需要在 基于 Asp.net mvc 的 Web 项目框架中做权限的控制,于是才有了这个权限控制组件. 项目 ...

  7. ant design pro (十六)advanced 权限管理

    一.概述 原文地址:https://pro.ant.design/docs/authority-management-cn 权限控制是中后台系统中常见的需求之一,你可以利用我们提供的权限控制组件,实现 ...

  8. Django - 权限(2)- 动态显示单级权限菜单

    一.权限组件 1.上篇随笔中,我们只是设计好了权限控制的表结构,有三个模型,五张表,两个多对多关系,并且简单实现了对用户的权限控制,我们会发现那样写有一个问题,就是权限控制写死在了项目中,并且没有实现 ...

  9. 【DRF权限】

    目录 权限的详细用法 我们都听过权限,那么权限到底是做什么的呢. 我们都有博客,或者去一些论坛,一定知道管理员这个角色, 比如我们申请博客的时候,一定要向管理员申请,也就是说管理员会有一些特殊的权利, ...

随机推荐

  1. Building QGIS from source - step by step(随笔3)

    依赖包安装 在编译QGIS前分别需要利用cygwin和OSGeo4W 安装网站上的依赖库.分别需要安装的依赖库可以参考官网,此外对应版本的ygwin和OSGeo4W 也可以在网站上找到下载链接. ht ...

  2. 我想要革命想要解脱——bootstrap常见问题及解决方式

    最近一个月,恍若隔世,天天加班,昨晚终于发版了,今天才喘一口气.有时候,即便你工作效率再怎么高,撸码再怎么快也无可避免的会加班.不信的话,可以先给你定一个交付时间,然后不断的给你加需求,就让你一个人做 ...

  3. Android 开源框架Glide的使用

    Glide是一个快速高效的多媒体管理和图像加载的框架,封装了Android平台的多媒体的解码,内存和硬盘缓存等,Glide支持解码.显示视频.图像和GIFs,Glide是基于定制的HttpUrlCon ...

  4. PSP总结报告

    此作业的要求参见[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2556] 回顾0 alpha阶段前 团队名称:可以低头,但没必要 团队项 ...

  5. c/c++ 继承与多态 继承时如何改变个别成员的访问属性

    问题1:若类B以private的方式继承类A,但还想让类A的某些个别成员,保持public或者protected的访问属性,这时应该怎么办? 使用using,去改变访问属性. #include < ...

  6. c/c++ 网络编程 使用getaddrinfo的单纯UDP 通信

    网络编程 使用getaddrinfo的单纯UDP 1,UDP发送端 2,UDP接收端 UDP发送端: #include <stdio.h> #include <unistd.h> ...

  7. Serverless架构

    什么是Serverless架构 Servlerless 架构是新兴的架构体系,在Serverless 架构中,开发者无需考虑服务器的问题,计算资源作为服务而不是服务器的概念出现,这样,开发者只需要关注 ...

  8. springboot项目屏蔽mq或者mongodb的监控日志输出

    最近写项目,用的是springboot,其中用到了rabbitmq和mongodb,配置完成 项目启动后,会输出如下日志: mongodb和mq的检测,会一直打印日志,这样会影响开发人员的测试. 如何 ...

  9. B. Creating the Contest(水题)

    直接水过 #include<iostream> #include<algorithm> using namespace std; ; int a[maxn]; int n, u ...

  10. Sqlserver查询死锁及杀死死锁的方法

    -- 查询死锁 select request_session_id spid, OBJECT_NAME(resource_associated_entity_id) tableName from sy ...