crm-3权限
1.权限基本实现
rbac: rbac基于角色的权限控制 ,权限本质就是url
权限表: url列表 角色表: 一个角色固定访问一些url的地址 用户表: 用户可以绑定角色 ,用户拥有了角色的权限
生成表数量: url权限表 + 角色表 + 用户表 + 权限角色对多对关系表 + 角色用户多对多关系表
2.rbac组件实现
基于角色的权限控制创建一个组件实现复用
1)创建权限表 + 角色表 + 用户表(因为之前项目有用户表 ,此表仅用作抽象类用于子类继承 ,建立映射但不做数据迁移)
####rbac/models
from django.db import models # Create your models here.
class Permisssion(models.Model):
url = models.CharField('含正则url', max_length=128)
title = models.CharField('权限标题', max_length=32, blank=True, null=True)
is_menu = models.BooleanField('是否为菜单', default=False) class Role(models.Model):
name = models.CharField('角色名称', max_length=32)
permissions = models.ManyToManyField('Permisssion', verbose_name='角色拥有权限') class rbacuser(models.Model):
name = models.CharField('用户名', max_length=32)
password = models.CharField('密码', max_length=32)
roles = models.ManyToManyField(Role, verbose_name='用户拥有角色') #这里面不在使用反射获取指定多对多 ,使用类名即可 # 用户表需要作为基类 让已有的user体系表去继承
class Meta:
abstract = True ####crm/models
class User(rbacuser, models.Model): #直接继承
...... ####数据迁移
2)权限的管理 ,使用admin系统对权限进行直观的管理
####rbac/admin
from django.contrib import admin # Register your models here.
from rbac import models
from crm.models import User # 设置配置类对某张表中展示的表字段做页面修改查看
class PermissionAdmin(admin.ModelAdmin):
list_display = ['pk', 'title', 'url', 'is_menu']
list_editable = ['url', 'is_menu'] # 注册时该表引用配置类
admin.site.register(models.Permisssion, PermissionAdmin)
admin.site.register(models.Role)
admin.site.register(User)
3)权限的流程控制
用户请求----wsgi----中间件----路由----view----返回数据
中间件: 增加白名单url(用于获取session) ,校验session权限
返回数据: 权限放入session中
4)用户登录功能 (白名单成员)
####urls
url(r'^login/', views.login.as_view(), name='login') ###crm/view
class login(View):
def get(self, request):
return render(request, 'login.html') def post(self, request):
name = request.POST.get('username')
password = request.POST.get('password')
md5 = hashlib.md5()
md5.update(password.encode('utf-8'))
md5_pwd = md5.hexdigest()
print(md5_pwd, name)
obj = models.User.objects.filter(name=name, password=md5_pwd)
print(obj)
if obj:
return redirect(reverse('crm:userlist'))
return HttpResponse('账号密码错误') ####html
{% load static %}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %} "/>
<link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.css' %} "/>
<link rel="stylesheet" href="{% static 'css/commons.css' %} "/>
<link rel="stylesheet" href="{% static 'css/nav.css' %} "/>
<link rel="stylesheet" href="{% static 'css/menu.css' %} "/> <title>login</title>
</head>
<body>
<form class="form-horizontal" method="post">
{% csrf_token %}
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">用户名</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="inputEmail3" name="username">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword3" name="password" placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox"> Remember me
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Sign in</button>
</div>
</div>
</form>
<script src="{% static 'js/jquery-3.3.1.min.js' %} "></script>
<script src="{% static 'plugins/bootstrap/js/bootstrap.js' %} "></script>
<script src="{% static 'js/menu.js' %} "></script>
</body>
</html>
5)白名单功能
settings中定义白名单 ,login算入白名单
rbac应用中创建中间件rbac/middlewares/rbac.py ,使用process_request完成校验白名单放行!
settings注册中间件注意顺序
####rbac中间件
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
from untitled import settings
import re class RbacMiddleWare(MiddlewareMixin):
def process_request(self, request):
url = request.path_info
for i in settings.VALID_LIST:
if re.match(i, url):
return
return HttpResponse('不在白名单中呢!!') ####settings配置中间件
'rbac.middlewares.rbac.RbacMiddleWare',
6)权限实现访问控制
login功能关键: 找到该用户的角色 ,并取出所有的权限去重, 放入session中
###crm/view 的login功能
from django.shortcuts import render, redirect, reverse, HttpResponse
from django.views import View
from crm import models
import hashlib # Create your views here.
class login(View):
def get(self, request):
return render(request, 'login.html') def post(self, request):
name = request.POST.get('username')
password = request.POST.get('password')
md5 = hashlib.md5()
md5.update(password.encode('utf-8'))
md5_pwd = md5.hexdigest()
print(md5_pwd, name)
obj = models.User.objects.filter(name=name, password=md5_pwd).first()
if not obj:
return HttpResponse('账号密码错误') # 如果用户登录成功!!此时取出该用户的权限放入session
# 该用户的(角色名 权限名 权限url)放入permisssion__query中去重(角色定义url重叠)
else:
permission_query = obj.roles.all().filter(permissions__url__isnull=False).values(
# 'name',
'permissions__title',
'permissions__url',
).distinct()
print(list(permission_query)) # 将对象列表转换为列表 ! 并将用户权限存入session
request.session['permissions'] = list(permission_query) # 此刻该用户登录成功
request.session['is_login'] = True return redirect(reverse('crm:userlist'))
中间件关键 : 判断白名单 --- 判断登录状态 --- 登录后不需权限访问的url --- 登录后需要权限访问的url(从login给的session中取出对应的权限校验一下)
####rbac/middlerware/rbac 中间件校验
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
from untitled import settings
import re class RbacMiddleWare(MiddlewareMixin):
def process_request(self, request):
url = request.path_info
# 白名单校验
for i in settings.VALID_LIST:
if re.match(i, url):
return
# 登录状态校验
is_login = request.session.get('is_login', None)
if not is_login:
return HttpResponse('未登录')
# 已登录 判断url是否不需要权限访问
for i in settings.NO_PERMISSION_LIST:
if re.match(i, url):
return
# 已登录 不在白名单 需要权限访问的url ,查看用户的权限
permission_list = request.session['permissions']
for i in permission_list:
re_url = i['permissions__url']
print(re_url)
if re.match(re_url, url):
return return HttpResponse('无权访问!!')
3.后端模板加工三种方法
filter #自定义管道过滤器 ,通过后端对变量做二次加工
simple_tag #展示执行函数的返回值
inclusion_tag #生成一小段代码 ,对比include而言能使用传参
使用方法: 三种方法的使用流程基本一致 ,仅装饰器不同
1)app下创建templatetags的py包
2)包中创建py文件
3)python文件写入
from django import template
register = template.Library()
filter 自定义加工变量(简单 ,但是参数唯一)
##rbac/templatetags/filter_test.py
from django import template register = template.Library() # 因为前端使用只有一个参数(value|add_str:arg)
@register.filter
def add_str(value, arg):
return '{}={}'.format(value, arg) ##html中引用 注意字符串需要加引号 ,也可以是后端内容
{% load filter_test %}
{{ 'ppp'|add_str:'lolo' }}
simple_tag 显示执行函数的返回值 (简单 ,还可以传入任意数量参数)
##rbac/templatetags/filter_test.py
from django import template register = template.Library() @register.simple_tag
def add_test(*args, **kwargs):
return '位置参数{} 关键字参数{}'.format('-'.join(args), '-'.join(kwargs.values())) ##html中应用 ,参数随便写
{% load my_define %}
{% add_test 'a' 'b' age='' name='屈冠文' %}
inclusion_tag 生成代码段 ,需要一个html文件存放代码段 ,在定义函数中引用 ,返回值放入html代码段 ,并在模板中引用函数执行(复杂 ,可以生成标签功能较好)
1)准备html代码段 2)准备函数返回值给到代码段处理 3)模板中执行函数返回代码段内容
##准备代码片段 rbac/templates/menu.html
{% for foo in num %}
<li>foo</li>
{% endfor %} ##返回值给到代码片段 rbac/templatetags/filter_test.py
from django import template register = template.Library() @register.inclusion_tag('menu.html')
def show_range(num):
return {'num': range(num)} ##html中load引用执行函数展示返回值
{% load my_define %}
{% block menu_list %}
{% show_range 10 %}
{% endblock %}
4. 根据权限实现一级菜单
1)动态生成一级菜单
login的登录函数 :
登陆成功后从数据库拿出用户的所有权限 ,并将权限放入permission_dict字典 ,再将字典中权限是菜单的放入menu_list列表中
将权限字典与菜单列表放入session中保存给用户
class login(View):
def get(self, request):
return render(request, 'login.html') def post(self, request):
name = request.POST.get('username')
password = request.POST.get('password')
md5 = hashlib.md5()
md5.update(password.encode('utf-8'))
md5_pwd = md5.hexdigest()
print(md5_pwd, name)
obj = models.User.objects.filter(name=name, password=md5_pwd).first()
if not obj:
return HttpResponse('账号密码错误') # 如果用户登录成功!!此时取出该用户的权限放入session
# 该用户的(角色名 权限名 权限url)放入permisssion__query中去重(角色定义url重叠)
else:
permission_query = obj.roles.all().filter(permissions__url__isnull=False).values(
# 'name',
'permissions__title',
'permissions__url',
'permissions__is_menu',
'permissions__name',
).distinct()
# print(permission_query) permission_dict = {}
menu_list = [] for i in permission_query:
permission_dict[i['permissions__name']] = {'url': i['permissions__url']}
if i['permissions__is_menu']:
menu_list.append({'title': i['permissions__title'], 'url': i['permissions__url']}) # 将对象列表转换为列表 ! 并将用户权限存入session
request.session[settings.PERMISSION_SESSION_KEY] = permission_dict
print(permission_dict)
request.session[settings.MENU_SESSION_KEY] = menu_list
# 此刻该用户登录成功
request.session['is_login'] = True return redirect(reverse('crm:deplist'))
rbac中间件:
遇到需要权限才能访问的url ,去session中将权限字典的value取出匹配 ,匹配成功就返回None表示通过
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
from untitled import settings
import re class RbacMiddleWare(MiddlewareMixin):
def process_request(self, request):
url = request.path_info
# 白名单校验
for i in settings.VALID_LIST:
if re.match(i, url):
return
# 登录状态校验
is_login = request.session.get('is_login', None)
if not is_login:
return HttpResponse('未登录')
# 已登录 判断url是否不需要权限访问
for i in settings.NO_PERMISSION_LIST:
if re.match(i, url):
return
# 已登录 不在白名单 需要权限访问的url ,查看用户的权限
permission_dict = request.session[settings.PERMISSION_SESSION_KEY]
for i in permission_dict.values():
re_url = '^'.format(i['url'])
if re.match(re_url, url):
return return HttpResponse('无权访问!!')
/rbac/templatetags/my_define自定义代码段后台:
使用inclusion_tag制作菜单代码段 ,函数接收模板中传过的request参数 ,取出request中的session的菜单列表, 对菜单列表中匹配的当前访问菜单添加active标记 ,将菜单列表返回给menu代码段
@register.inclusion_tag('menu.html')
def menu(request):
url_now = request.path_info
menu_list = request.session[settings.MENU_SESSION_KEY]
for i in menu_list:
# 重点标记当前访问的菜单
if re.match('^{}'.format(i['url']), url_now):
i['class'] = 'active'
return {'menu_list': menu_list}
/rbac/template/menu.html自定义代码段前端:
代码段接收到my_define的返回值进行生成代码段 ...
{% for menu in menu_list %}
<div class="static-menu">
<a class="{{ menu.class }}" href="{{ menu.url }}"><span class="icon-wrap"><i class="fa fa-map-o" aria-hidden="true"></i></span>{{ menu.title }}</a>
</div>
{% endfor %}
/layout.html模板
菜单是通用内容放在了 ,所以放在了母板中 ,母板中执行my_define ,并展示menu.html
{% load my_define %}
{% menu request %}
2)限制到按钮级别 ,展示部门中有新增的一个按钮 ,但是必须拥有add权限的用户才能显示使用 (后续edit也需要修改)
原理: 通过模板中传过来的request对象与参数(url别名), 在permission_dict字典中判断如果有url别名返回true ,其中url别名是个关键点 ,url别名是专用去匹配前端的参数的 (前面构建数据格式已经将别名转为字典的key值)
####校验某个按钮权限my_define.py
@register.filter def has_permission(request, name): if name in request.session[settings.PERMISSION_SESSION_KEY]: return True ####母版文件中判断是否给该用户展示layout.html
{% load my_define %}
{% if request|has_permission:'dep_add' %}
<a class="btn btn-sm btn-primary" href="{% url 'crm:depadd' %}"><span class="icon-wrap"><i
class="fa fa-map-o"
aria-hidden="true"></i></span>新增
</a>
{% endif %}
crm-3权限的更多相关文章
- Dynamics CRM 2011 权限管理(转)
http://www.cnblogs.com/LeoTang/p/3344265.html Dynamics CRM 2011 权限管理 CRM系统基于角色的权限主要通过部门.角色.用户.团队来 进行 ...
- Django项目:CRM(客户关系管理系统)--85--75PerfectCRM实现CRM扩展权限
# sales_urls.py # ————————47PerfectCRM实现CRM客户报名流程———————— from django.conf.urls import url from bpm. ...
- crm操作权限
using System; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using System.Colle ...
- python 全栈开发,Day107(CRM初始,权限组件之权限控制,权限系统表设计)
一.CRM初始 CRM,客户关系管理系统(Customer Relationship Management).企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销 ...
- Dynamics CRM 2011 权限管理
CRM系统基于角色的权限主要通过部门.角色.用户.团队来进行控制.每一个实体记录的所有者(Owner)必然是某一个用户或团队.一个用户或团队必然归属于一个且只归属于一个部门,但团队的成员即用户可以来自 ...
- day28 CRM万能权限组件开发 && 主机管理-堡垒机
1,CRM项目实战-万能权限组件开发参考博客:http://www.cnblogs.com/alex3714/articles/6661911.html 参考代码:https://github.com ...
- day 71 crm(8) 权限组件的设置,以及权限组件的应用
---恢复内容开始--- 前情提要: strak 组件是增删改查组件 , 生活中,需求权限组件, 不足: 1,前后端不分离, 2, 空url也会刷新界面,造成资源浪费 3,如果角色忘记设置权 ...
- crm项目-权限组件
############### 表结构分析 ################ """ 表结构设计: 1,四张表 用户表,userinfo,这个表本身不会被创 ...
- Dynamics CRM 权限整理二
接上篇http://blog.csdn.net/vic0228/article/details/50510605,继续列举CRM相关权限 prvReadBusinessUnit privilege(I ...
- CRM项目之RBAC权限组件-day26
写在前面 上课第26天,打卡: 世间安得双全法 不负如来不负卿 s17day26 CRM项目 项目概要:XX公司CRM - 权限管理,公共组件,app ***** - 熟悉增删改查,Low *** - ...
随机推荐
- Linux中,Tomcat 怎么承载高并发(深入Tcp参数 backlog)
一.前言 这两天看tomcat,查阅 tomcat 怎么承载高并发时,看到了backlog参数.我们知道,服务器端一般使用mq来减轻高并发下的洪峰冲击,将暂时不能处理的请求放入队列,后续再慢慢处理.其 ...
- 记一次Ubuntu19无法安装docker源
按照各大网站以及个人习惯我会使用下面这种方法添加Docker源: root@ubuntu:~# sudo add-apt-repository "deb [arch=amd64] https ...
- 基于STM32F429,Cubemx的SAI音频播放实验
书接上文:https://www.cnblogs.com/feiniaoliangtiangao/p/11060674.html 和 https://www.cnblogs.com/feiniaoli ...
- 【LeetCode】11. 盛最多水的容器
题目 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0).找出其中的两 ...
- 史诗级最强教科书式“NIO与Netty编程”
史诗级最强教科书式“NIO与Netty编程” 1.1 概述 1.2 文件IO 1.2.1 概述和核心API 1.2.2 案例 1.3 网络IO 1.3.1 概述和核心API 3.4 AIO编程 3.5 ...
- IDEA中新建SpringBoot项目时提示:Artifact contains illegal characters
场景 一步一步教你在IEDA中快速搭建SpringBoot项目: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/87688277 ...
- Java数据类型和自动拆装箱
1.java的数据类型:基本数据类型(8种)和引用数据类型. 基本数据类型: 类型 boolean byte short char int long float double 位 1 8 16 16 ...
- 解决html导出pdf中文乱码问题的正确姿势
简介 本文使用jspdf 1.5.3版.GitHub地址:https://github.com/MrRio/jsPDF jspdf是歪果仁开发的,因此在一开始就没想过支持非英文以外的文字,这就导致了非 ...
- August 04th, 2019. Week 32nd, Sunday
Making peace with what you don't have, that's what it's all about. 人生在世,不如意者十之八九,保持平常心,命里无时莫强求. Ever ...
- Java流程控制之选择语句
选择语句 选择语句也称之为判断语句,主要有2种写法,一种是if语句,一种是switch语句.下面我们就详细的介绍一下这2种语句的用法. 判断语句if if语句第一种形式: if 格式: 执行流程 首先 ...