rbac组件之权限初始化(五)

当用户登陆后,根据用户的角色要为用户生成对应的权限菜单,此时需要将登陆的用户信息获取且获取角色信息,从数据库中获取菜单以及权限信息,并且存入session中。

1、权限流程

第一次请求的页面是登陆页面,已经被列入白名单,根据登陆的用户信息,获取用户的角色信息,从而拿到一个或者多个角色的权限、菜单信息,并且将其保存在session中,当用户第二次发起请求时,通过权限校验(通过之前保存在session中的信息,利用中间件进行校验),获取用户的菜单和权限信息,这样就完成了用户权限的设置。

 rbac组件之权限初始化(五)

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}
rbac组件之权限初始化(五)
<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 rbac组件之权限初始化(五)
{% 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

 

上一篇:Java EE 6中的编程身份验证


下一篇:权限组件(6):权限分配的角色管理