zoukankan      html  css  js  c++  java
  • rbac组件之权限初始化(五)

    当用户登陆后,根据用户的角色要为用户生成对应的权限菜单,此时需要将登陆的用户信息获取且获取角色信息,从数据库中获取菜单以及权限信息,并且存入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
  • 相关阅读:
    扩展卢卡斯定理
    扩展中国剩余定理
    扩展欧拉定理
    拓展BSGS
    删边最短路
    树 上 差分
    P4568 JLOI 飞行路线 分层最短路板子
    最短路相关
    P3758 TJOI2017 可乐
    bzoj4173 数学
  • 原文地址:https://www.cnblogs.com/shenjianping/p/10964406.html
Copyright © 2011-2022 走看看