zoukankan      html  css  js  c++  java
  • python 权限系统设计

    权限系统表结构的设计

    from django.db import models
    
    # Create your models here.
    class UserInfo(models.Model):
        '''
        用户表
        '''
        username=models.CharField(max_length=32,verbose_name='用户名')
        password=models.CharField(max_length=64,verbose_name='密码')
        roles=models.ManyToManyField(to='Role',verbose_name='拥有角色',)
    class Role(models.Model):
        '''
        角色表
        '''
        title=models.CharField(max_length=32,verbose_name='角色名称')
        permissions=models.ManyToManyField(to='Permission',verbose_name='拥有权限')
        def __str__(self):
            return self.title
    
    class Permission(models.Model):
        '''
        权限表
        '''
        title=models.CharField(max_length=32,verbose_name='权限名称')
        url=models.CharField(max_length=255,verbose_name='含权限的URL')
        code=models.CharField(max_length=32,verbose_name='权限代码')
        group=models.ForeignKey(to='PermissionGroup',verbose_name='所属权限组',on_delete=True)
        group_menu=models.ForeignKey(verbose_name='组内菜单',to='self',null=True,blank=True,related_name='gxx',on_delete=True)
    class PermissionGroup(models.Model):
        '''
        权限组
        '''
        caption=models.CharField(max_length=32,verbose_name='权限组名称')
        menu=models.ForeignKey(to='Menu',on_delete=True)
    class Menu(models.Model):
        '''
        菜单表
        '''
        title=models.CharField(max_length=32)

    权限系统需要在django项目settings.py 中设置如下

    PERMISSION_DICT_SESSION_KEY='user_permission_dict_key'   #权限字典存入session中
    PERMISSION_MENU_SESSION_KEY='user_permission_menu_key'   #权限目录放入session中
    REX_FORMAT = "^%s$"                        #url的匹配头部和结尾设置
    VALID_LIST = [                             #url的访问白名单
        '/crm/login/',
        '^/admin/.*',
    ]

    权限系统的app中建立services包,init_permission.py 文件 把权限的url存入session中,把权限的目录存入session中

    from  django.conf import settings
    def init_permission(user,request):
        '''
        登录用户的权限初始化
        :param user:登录用户对象
        :param request:
        :return:
        '''
        permisssions_list = user.roles.filter(permissions__id__isnull=False).values(
            'permissions__id',#权限id
            'permissions__title',#权限名称
            'permissions__url',#权限url
            'permissions__code',#权限code
            'permissions__group__id',#权限组id
            'permissions__group_menu__id',#是否为组内菜单
            'permissions__group__menu__id',#一级菜单id
            'permissions__group__menu__title',#一级菜单名称
        ).distinct()
        #获取权限信息+菜单放入session 中,以后生成动态菜单
        permission_menu_list=[]
        for item in permisssions_list:
            val={
                'id':item['permissions__id'],
                'title':item['permissions__title'],
                'url':item['permissions__url'],
                'pid':item['permissions__group_menu__id'],
                'menu_id':item['permissions__group__menu__id'],
                'menu_name':item['permissions__group__menu__title'],
            }
            permission_menu_list.append(val)
        request.session[settings.PERMISSION_MENU_SESSION_KEY]=permission_menu_list
        #获取权限信息放入session中
        permission_dict = {}
        for permission in permisssions_list:
            group_ip = permission['permissions__group__id']
            url = permission['permissions__url']
            code = permission['permissions__code']
            if group_ip in permission_dict:
                permission_dict[group_ip]['urls'].append(url)
                permission_dict[group_ip]['codes'].append(code)
            else:
                permission_dict[group_ip] = {'urls': [url, ], 'codes': [code, ]}
        request.session[settings.PERMISSION_DICT_SESSION_KEY]=permission_dict

    权限系统的app中建立templatetags包,rbac.py 文件  构造权限目录

    from django.template import Library
    from django.conf import settings
    import re
    register=Library()
    @register.inclusion_tag('rbac/menu.html')
    def menu(request):
        permission_menu_list = request.session[settings.PERMISSION_MENU_SESSION_KEY]
        current_url = request.path_info
        current_pxe = settings.REX_FORMAT
    
        # 构造二级菜单字典
        per_dict = {}
        for per_item in permission_menu_list:
            if not per_item['pid']:
                per_dict[per_item['id']] = per_item
        for item in permission_menu_list:
            if not re.match(current_pxe % (item['url']), current_url):
                continue
            if item['pid']:
                per_dict[item['pid']]['active'] = True
            else:
                item['active'] = True
        # 生成菜单字典
        menu_dict = {}
        for menu_item in per_dict.values():
            if menu_item['menu_id'] in menu_dict:
                menu_dict[menu_item['menu_id']]['children'].append(
                    {'id': menu_item['id'], "title": menu_item['title'], 'url': menu_item['url'],
                     'active': menu_item.get('active', False)})
                # menu_item['menu_id']['children'].append({'id':menu_item['id'],"title":menu_item['title'],'url':menu_item['url'],'active':menu_item.get('active',False)})
                if menu_item.get('active', False):
                    menu_item['menu_id']['active']: True
                # menu_item['menu_id']['children'].append({'id':menu_item['id'],"title":menu_item['title'],'url':menu_item['url'],'active':menu_item.get('active',False)})
            else:
                menu_dict[menu_item['menu_id']] = {
                    'menu_name': menu_item['menu_name'],
                    'active': menu_item.get('active', False),
                    'children': [{'id': menu_item['id'], "title": menu_item['title'], 'url': menu_item['url'],
                                  'active': menu_item.get('active', False)}]
                }
        return {'menu_dict':menu_dict}

    权限系统的app中建立templates/rbac/menu.html 文件  构造权限的html页面 

    {% for menu in menu_dict.values %}
                    <div class="con-menu">
                        <div class="menu-name">{{ menu.menu_name }}</div>
    
                        <div class="menu-item">
                            {% for item  in menu.children  %}
                                {% if item.active %}
                                    <a href="{{ item.url }}" class="active">{{ item.title }}</a>
                                {% else %}
                                    <a href="{{ item.url }}">{{ item.title }}</a>
                                {% endif %}
    
                            {% endfor %}
                        </div>
                    </div>
                {% endfor %}

    在 要使用权限系统的app中 的布局页面,中把 menu.html 页面个包含到目录位置

    {% load rbac %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            body{
                margin: 0;
            }
            .pg-head{
                height: 48px;
                background-color: darkgray;
            }
            .menu{
                position: absolute;
                top:48px;
                left: 0px;
                bottom: 0px;
                width: 100px;
                background-color: whitesmoke;
            }
            .content{
                position: absolute;
                top: 48px;
                left: 100px;
                right: 0px;
                bottom: 0px;
                overflow: auto;
                background-color: aliceblue;
            }
            .con-menu .menu-name{
                background-color: beige;
            }
    
            .con-menu .menu-item a{
                display: block;
                margin-left: 10px;
            }
             .con-menu .menu-item a.active{
                 color: aquamarine;
             }
        </style>
    </head>
    <body>
        <div class="pg-head">头部菜单</div>
        <div class="pg-body">
            <div class="menu">
                {% menu request %}
            </div>
            <div class="content">
                    {% block content  %}
                    {% endblock %}
            </div>
        </div>
    </body>
    </html>

     权限系统中的权限的验证时放在中间件找那个实现的

    MIDDLEWARE = [
        #'django.middleware.cache.UpdateCacheMiddleware',
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        #'django.middleware.cache.FetchFromCacheMiddleware',
        'rbac.middlewares.rbac.RbacMiddleware', # 权限验证的中间件
    ]

    权限中间件  在 rbac app 中创建 middlewares包创建rbac.py文件 在其中创建 继承中间件的类,实现用户登录权限的验证。

    from django.conf import settings
    from  django.shortcuts import HttpResponse
    import re
    class MiddlewareMixin(object):
        def __init__(self, get_response=None):
            self.get_response = get_response
            super().__init__()
    
        def __call__(self, request):
            response = None
            if hasattr(self, 'process_request'):
                response = self.process_request(request)
            if not response:
                response = self.get_response(request)
            if hasattr(self, 'process_response'):
                response = self.process_response(request, response)
            return response
    
    class RbacMiddleware(MiddlewareMixin):
        def process_request(self,request):
           #访问白名单
            current_url = request.path_info
            white_list=settings.VALID_LIST
            # if current_url=='/crm/login/':
            #     return None
            for valid_item in white_list:
                if re.match(valid_item,current_url):
                    return None
            #获取用户的权限信息
            permission_dict=request.session.get(settings.PERMISSION_DICT_SESSION_KEY)
            #print(permission_dict)
            if not permission_dict:
                return HttpResponse('当前用户无权限信息.')
            #匹配用户是否拥有访问当前页面的权限
            flag=False
            for permission_item in permission_dict.values():
                urls=permission_item['urls']
                codes=permission_item['codes']
    
                for itme_url in urls:
                    reg=settings.REX_FORMAT %(itme_url)
                    if re.match(reg,current_url):
                        request.permission_codes = codes
                        print(request.permission_codes)
                        flag=True
                        break
                if flag:
                    break
            if not flag:
                return HttpResponse('无权访问.')
  • 相关阅读:
    [转]c++访问python3-实例化类的方法
    【转】利用Boost.Python将C++代码封装为Python模块
    [转]Linux下Python与C++混合编程
    [转]Windows下使用VS2015编译openssl库
    [转]boost::python开发环境搭建
    [转]linux下编译boost.python
    [转]阿里巴巴十年Java架构师分享,会了这个知识点的人都去BAT了
    [转]Python3《机器学习实战》学习笔记(一):k-近邻算法(史诗级干货长文)
    [转]马上2018年了,该不该下定决心转型AI呢
    [转]PostgreSQL命令行使用手册
  • 原文地址:https://www.cnblogs.com/hexintong/p/9558711.html
Copyright © 2011-2022 走看看