rbac组件之权限初始化(五)
2024-08-24 05:20:56
当用户登陆后,根据用户的角色要为用户生成对应的权限菜单,此时需要将登陆的用户信息获取且获取角色信息,从数据库中获取菜单以及权限信息,并且存入session中。
1、权限流程
第一次请求的页面是登陆页面,已经被列入白名单,根据登陆的用户信息,获取用户的角色信息,从而拿到一个或者多个角色的权限、菜单信息,并且将其保存在session中,当用户第二次发起请求时,通过权限校验(通过之前保存在session中的信息,利用中间件进行校验),获取用户的菜单和权限信息,这样就完成了用户权限的设置。
2、权限初始化
从数据库中获取该用户的权限和菜单信息,并且存入session中。
from django.conf import settings class InitPermission(object): def __init__(self,request,user):
"""
:param request: 传入request对象
:param user: 传入用户对象
""" self.request=request
self.user=user
self.menu_dict={}
self.permissions_dict={} def init_data(self):
"""
从数据库中获取权限信息以及用户信息
:return:
"""
self.permissions_queryset=self.user.roles.filter(permissions__url__isnull=False).values(
'permissions__id',
'permissions__url',
'permissions__title',
'permissions__name',
'permissions__parent_id',
'permissions__parent__name',
'permissions__menu_id',
'permissions__menu__title',
'permissions__menu__icon',
).distinct()
return self.permissions_queryset def init_permissions_dict(self):
"""
构建权限列表,并且存入session
self.permissions_dict={
'customer_list':{'id':1,'url':'/customer/list/','title':'客户列表','pid':'父权限id'}
...
}
:return:
"""
for row in self.init_data():
self.permissions_dict[row['permissions__name']]={
'id':row['permissions__id'],
'url': row['permissions__url'],
'title': row['permissions__title'],
'pid':row['permissions__parent_id'],
'pname':row['permissions__parent__name'],
}
self.request.session[settings.PERMISSION_SESSION_KEY]=self.permissions_dict def init_menu_dict(self):
"""
构建菜单字典并且存入session,之所以构建字典,可以通过键值进行排序
self.menu_dict={
1:{
title:'客户管理',icon:'fa fa-coffe',children:[
{'id':1,'url':'/customer/list/','title':'客户列表'}
...
]
}
}
:return:
"""
for row in self.init_data():
menu_id=row['permissions__menu_id']
if not menu_id:
continue
if menu_id not in self.menu_dict:
self.menu_dict[menu_id]={
'title': row['permissions__menu__title'],
'icon': row['permissions__menu__icon'],
'children': [
{'id':row['permissions__id'],'title': row['permissions__title'], 'url': row['permissions__url']}
]
}
else:
self.menu_dict[menu_id]['children'].append(
{'id': row['permissions__id'], 'title': row['permissions__title'], 'url': row['permissions__url']}
)
self.request.session[settings.MENU_SESSION_KEY] = self.menu_dict
3、权限校验
当用户进行登陆时,需要进行权限校验,通过中间件进行判断。
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse,redirect
from django.conf import settings
import re class PermissionMiddleWare(MiddlewareMixin):
"""
权限控制的中间件
""" def process_request(self, request):
"""
权限控制
:param request:
:return:
"""
# 1. 获取当前请求URL
current_url = request.path_info
print('current_path',current_url) # 1.5 白名单处理
for reg in settings.VALID_URL:
if re.match(reg,current_url):
return None # 2. 获取当前用户session中所有的权限
permissions_dict = request.session.get(settings.PERMISSION_SESSION_KEY)
if not permissions_dict:
return redirect('/login/') # 3. 进行权限校验
flag = False
request.breadcrumb_list=[{'title':'首页','url':'/index/'}]
for item in permissions_dict.values():
id=item['id']
pid=item['pid']
reg = "%s$" % item['url']
print('reg',reg)
if re.match(reg, current_url):
if pid: #访问的是添加客户网页
request.current_menu_id=pid #让它与可以作为权限菜单的客户列表挂钩
###导航条自动生成
request.breadcrumb_list.extend([
{'title':permissions_dict[item['pname']]['title'],'url':permissions_dict[item['pname']]['url']},
{'title':item['title'],'url':item['url']}
]
)
else:
request.current_menu_id=id
###导航条自动生成
request.breadcrumb_list.extend([
{'title':item['title'],'url':item['url']}
]
)
flag = True
break
if not flag:
return HttpResponse('无权访问')
4、前端生成页面
前端生成menu菜单以及breadcrumb导航条
...
<div class="pg-body">
<div class="left-menu">
<div class="menu-body">
{% menu request %}
</div>
</div>
<div class="right-body">
<div>
<ol class="breadcrumb no-radius no-margin" style="border-bottom: 1px solid #ddd;">
{% breadcrumb request %}
</ol>
</div>
{% block content %} {% endblock %}
</div>
</div>
...
menu.py
from django.template import Library
from django.conf import settings
from collections import OrderedDict register=Library() @register.inclusion_tag('rbac/menu.html')
def menu(request):
#获取session中的菜单列表
menu_dict=request.session.get(settings.MENU_SESSION_KEY)
order_dict=OrderedDict()
if menu_dict:
for key in sorted(menu_dict): #按照菜单id升序对菜单进行排序
order_dict[key]=menu_dict[key]
menu_dict[key]['class']='hide'
for child in menu_dict[key]['children']:
if request.current_menu_id==child['id']: #非菜单权限以及菜单权限默认展开
child['class']='active'
menu_dict[key]['class'] = ''
return {"menu_dict":menu_dict} @register.inclusion_tag('rbac/breadcrumb.html')
def breadcrumb(request):
return {'breadcrumb_list':request.breadcrumb_list}
<div class="multi-menu"> {% for item in menu_dict.values %}
<div class="item">
<div class="title"><span class="icon-wrap"><i class="{{ item.icon }}"></i></span> {{ item.title }}</div>
<div class="body {{ item.class }}">
{% for child in item.children %}
<a href="{{ child.url }}" class="{{ child.class }}">{{ child.title }}</a>
{% endfor %}
</div>
</div>
{% endfor %} </div>
menu.html
{% for item in breadcrumb_list %}
{% if forloop.last %}
<li class="active">{{ item.title }}</li>
{% else %}
<li><a href="{{ item.url }}" >{{ item.title }}</a></li>
{% endif %}
{% endfor %}
breadcrumb.html
最新文章
- 校友聊NABCD
- vtigerCRM5.4的安装和汉化 ubuntu
- 创建一个hibernate helloword
- Struts2中date标签乱码问题解决
- Activiti5.16.4数据库表结构
- Python: 设计模式 之 工厂模式例(1)
- python运算符使用规律
- opensatck 在启动的时候注入额外的信息
- JavaScript设计模式_05_发布订阅模式
- 工具 | 代码调试利器fiddle介绍
- jQuery+ajax实现局部刷新
- Asp.net mvc 5 razor
- 【Jest】笔记一:环境配置
- HDU5542 The Battle of Chibi
- Feign快速入门
- 原生js--文档加载时间
- 转:Java中字符串split() 的使用方法.
- 多线程私有数据pthread_key_create
- Composer 技巧(以 FastAdmin 项目为基础)(2018-12-25 更新)
- Python(socketserver并发聊天)