当用户登陆后,根据用户的角色要为用户生成对应的权限菜单,此时需要将登陆的用户信息获取且获取角色信息,从数据库中获取菜单以及权限信息,并且存入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>
{% 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 %}