zoukankan      html  css  js  c++  java
  • rbac(基于角色权限控制)-------权限管理


    权限管理
      创建一个rbac和app的应用,这个rbac主要是用来存放权限的,全称叫做基于角色权限控制
      一、先看配置文件合适不,给创建的rbac在配置文件里面设置一下
        找到INSTALLED_APPS=【'rbac'】
      二、设计表结构
        models中创建类:五个类,七张表
        角色表:
        用户表:
        权限表:

         组表:

         菜单表:

        角色表和权限表是多对多的关系(一个角色可以有多个权限,一个权限可以对应多个角色)
        用户表和角色表是多对多的关系(一个用户可以有多个角色,一个角色有多个用户)

        所以有会多生成两张关系表

        一个菜单下面有多个组

        一个组下面有多个菜单

        一个菜单下面有多个权限

    复制代码
    from django.db import models
    

    # Create your models here.
    class Role(models.Model):
    '''
    角色表
    '''
    title
    = models.CharField(max_length=32,verbose_name="角色名")
    permissions
    = models.ManyToManyField(to="Permission",verbose_name="具有的所有权限", blank=True) # 建立用户表和角色表的多对多关系

    <span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.title
    
    </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Meta:
        verbose_name_plural </span>= <span style="color: #800000;">"</span><span style="color: #800000;">角色表</span><span style="color: #800000;">"</span>
    

    class Group(models.Model):
    caption
    = models.CharField(max_length=32,verbose_name="组名称")
    menu
    = models.ForeignKey(to="Menu",verbose_name="所属菜单",default=1,related_name="menu")
    class Menu(models.Model):
    title
    = models.CharField(max_length=32)

    class Permission(models.Model):
    '''
    权限表
    '''
    title
    = models.CharField(max_length=32,verbose_name="标题")
    url
    = models.CharField(max_length=64,verbose_name="带正则的URL")
    # is_mune = models.BooleanField(verbose_name="是否是菜单",default=0)
    menu_gp = models.ForeignKey(verbose_name="组内菜单",to="Permission",blank=True,null=True) #自关联
    #主页就可以设置为菜单,当点击菜单的时候才可以做具体的操作
    codes = models.CharField(max_length=32,verbose_name="代码",default=1)
    group
    = models.ForeignKey(to="Group",verbose_name="所属组",null=True) #新添加的字段记得设置默认值

    <span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.title
    
    </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Meta:
        </span><span style="color: #800000;">'''</span><span style="color: #800000;">中文显示</span><span style="color: #800000;">'''</span><span style="color: #000000;">
        verbose_name_plural </span>= <span style="color: #800000;">"</span><span style="color: #800000;">权限表</span><span style="color: #800000;">"</span>
    

    class UserInfo(models.Model):
    '''
    用户表
    '''
    username
    = models.CharField(max_length=32,verbose_name="用户名")
    password
    = models.CharField(max_length=64,verbose_name="密码")
    email
    = models.CharField(max_length=32,verbose_name="邮箱")
    roles
    = models.ManyToManyField(to="Role",verbose_name="具有的所有角色",blank=True) #建立用户和角色的多对多关系

    <span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.username
    
    </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Meta:
        verbose_name_plural </span>= <span style="color: #800000;">"</span><span style="color: #800000;">用户表</span><span style="color: #800000;">"</span></pre>
    
    复制代码


      三、通过django admin录入权限数据
        - 先创建一个超级用户
        - 用户名 root
        - 密码 zhy123456
        - 在admin.py 中
          from rbac import models
          admin.site.register(models.Permission)
          admin.site.register(models.Role)
          admin.site.register(models.UserInfo)
          这样的话上去的是英文的,如果你想让中文显示就在类中加一个类
          class Meta:
          verbose_name_plural = "权限表"
          - 当你给关联字段录入数据的时候会有错误提示,那么在类中你的那个关联字段在加一个属性blank = True 可以为空
          permissions = models.ManyToManyField(to="Permission",verbose_name="具有的所有权限", blank=True)

      四、编写登录
        用户登录后:
          获取当前用户具有的所有角色
          获取当前用户具有的所有权限(并且去重)

    复制代码
          #获取当前的用户对象
          user = models.UserInfo.objects.filter(username=name,password=password).first()
          #获取当前用户的所有角色user.roles.all()
          #获取当前用户的所有权限
          permission_list = user.roles.all().values("permissions__title","permissions__url","permissions__is_mune").distinct()
          print(permission_list)
    复制代码

          登录成功之后初始化---把所有的url都拿出来并且保存到session里
            1、可以建一个server的包,在里面建一个初始化的init_perssion.py文件
            2、定义函数

    复制代码
    #!usr/bin/env python
    # -*- coding:utf-8 -*-
    from rbac import models
    from day7权限管理 import settings
    def init_permission(user,request):
        #获取当前的用户对象
        '''
        获取所有权限中的url并放在session中
        :param user:
        :param request:
        :return:
        '''
    
    <span style="color: #008000;">#</span><span style="color: #008000;">user.roles.all()获取当前用户的所有角色</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">获取当前用户的所有权限</span>
    permission_list =<span style="color: #000000;"> user.roles.all().values(
        </span><span style="color: #800000;">"</span><span style="color: #800000;">permissions__id</span><span style="color: #800000;">"</span><span style="color: #000000;">,
        </span><span style="color: #800000;">"</span><span style="color: #800000;">permissions__title</span><span style="color: #800000;">"</span>,  <span style="color: #008000;">#</span><span style="color: #008000;">用户列表</span>
        <span style="color: #800000;">"</span><span style="color: #800000;">permissions__url</span><span style="color: #800000;">"</span>,    <span style="color: #008000;">#</span><span style="color: #008000;">url</span>
        <span style="color: #800000;">"</span><span style="color: #800000;">permissions__menu_gp</span><span style="color: #800000;">"</span>,  <span style="color: #008000;">#</span><span style="color: #008000;">组内菜单id,如果为null表示是菜单</span>
        <span style="color: #800000;">"</span><span style="color: #800000;">permissions__codes</span><span style="color: #800000;">"</span><span style="color: #000000;">,
        </span><span style="color: #800000;">"</span><span style="color: #800000;">permissions__group_id</span><span style="color: #800000;">"</span><span style="color: #000000;">,
        </span><span style="color: #800000;">"</span><span style="color: #800000;">permissions__group__menu__title</span><span style="color: #800000;">"</span>,  <span style="color: #008000;">#</span><span style="color: #008000;">菜单名称</span>
        <span style="color: #800000;">"</span><span style="color: #800000;">permissions__group__menu__id</span><span style="color: #800000;">"</span>  <span style="color: #008000;">#</span><span style="color: #008000;">菜单id</span>
    

    ).distinct()

    </span><span style="color: #0000ff;">print</span>(<span style="color: #800000;">"</span><span style="color: #800000;">-----------------</span><span style="color: #800000;">"</span><span style="color: #000000;">,permission_list)
    </span><span style="color: #008000;">#</span><span style="color: #008000;">菜单相关</span>
    sub_permisson_list =<span style="color: #000000;"> []
    </span><span style="color: #0000ff;">for</span> item <span style="color: #0000ff;">in</span><span style="color: #000000;"> permission_list:
        tpl </span>=<span style="color: #000000;"> {
            </span><span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__id</span><span style="color: #800000;">"</span><span style="color: #000000;">],
            </span><span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__title</span><span style="color: #800000;">"</span><span style="color: #000000;">],
            </span><span style="color: #800000;">"</span><span style="color: #800000;">url</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__url</span><span style="color: #800000;">"</span><span style="color: #000000;">],
            </span><span style="color: #800000;">"</span><span style="color: #800000;">menu_group_id</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__group_id</span><span style="color: #800000;">"</span><span style="color: #000000;">],
            </span><span style="color: #800000;">"</span><span style="color: #800000;">menu_id</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__group__menu__id</span><span style="color: #800000;">"</span><span style="color: #000000;">],
            </span><span style="color: #800000;">"</span><span style="color: #800000;">menu_title</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__group__menu__title</span><span style="color: #800000;">"</span><span style="color: #000000;">]
        }
        sub_permisson_list.append(tpl)
    request.session[settings.PERMISSION_MENU_KEY] </span>=<span style="color: #000000;"> sub_permisson_list
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> 1、去掉不是菜单的url</span>
    <span style="color: #008000;">#</span><span style="color: #008000;"> 菜单操作</span>
    <span style="color: #008000;">#</span><span style="color: #008000;"> menu_list = []</span>
    <span style="color: #008000;">#</span><span style="color: #008000;"> for item in permission_list:</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">     if not item["permissions__is_mune"]:  # 如果不是菜单就继续</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">         continue</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">     else:  # 否则是菜单的话就把菜单添加到列表里面</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">         tpl = {</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "menu_id": item["permissions__group__menu__id"],</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "menu_title": item["permissions__group__menu__title"],</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "title": item["permissions__title"],</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "url": item["permissions__url"],</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "active": False</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">         }</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">         menu_list.append(tpl)</span>
    <span style="color: #008000;">#</span><span style="color: #008000;"> request.session[settings.PERMISSION_MENU_KEY] = menu_list  #吧所有的菜单都放在session里面</span>
    <span style="color: #008000;">#</span><span style="color: #008000;"> print("xcvxvxv", menu_list)</span>
    
    
    
    <span style="color: #008000;">#</span><span style="color: #008000;"> 权限相关</span>
    result =<span style="color: #000000;"> {}
    </span><span style="color: #0000ff;">for</span> item <span style="color: #0000ff;">in</span><span style="color: #000000;"> permission_list:
        group_id </span>= item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__group_id</span><span style="color: #800000;">"</span><span style="color: #000000;">]
        url </span>=item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__url</span><span style="color: #800000;">"</span><span style="color: #000000;">]
        code </span>= item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__codes</span><span style="color: #800000;">"</span><span style="color: #000000;">]
        </span><span style="color: #0000ff;">if</span> group_id <span style="color: #0000ff;">in</span><span style="color: #000000;"> result:
            </span><span style="color: #008000;">#</span><span style="color: #008000;">如果在说明url和code已经生成了</span>
            result[group_id][<span style="color: #800000;">"</span><span style="color: #800000;">codes</span><span style="color: #800000;">"</span><span style="color: #000000;">].append(code)
            result[group_id][</span><span style="color: #800000;">"</span><span style="color: #800000;">urls</span><span style="color: #800000;">"</span><span style="color: #000000;">].append(url)
        </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
            </span><span style="color: #008000;">#</span><span style="color: #008000;">如果不在就添加进去</span>
            result[group_id] =<span style="color: #000000;">{
                </span><span style="color: #800000;">"</span><span style="color: #800000;">codes</span><span style="color: #800000;">"</span><span style="color: #000000;">:[code,],
                </span><span style="color: #800000;">"</span><span style="color: #800000;">urls</span><span style="color: #800000;">"</span><span style="color: #000000;">:[url]
            }
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> print(result)</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">吧所有权限中的url字典放到session中</span>
    request.session[settings.PERMISSION_URL_DICT_KEY] =<span style="color: #000000;"> result
    
    
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> # 打印的结果如下</span>
    <span style="color: #008000;">#</span><span style="color: #008000;"> result = {</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">     1: {</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">         "codes": ["list", "add", "del", "edit"]</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">         "urls": [</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "/userinfo/",</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "/userinfo/add" ,</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "/userinfo/del(d+)/ ",</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "/userinfo/edit(d+)/ ",</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">         ]</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">     },</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">     2: {</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">         "codes": {"list", "add", "del", "edit"}</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">          "urls": [</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "/order",</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "/order/add" ,</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "/order/del(d+)/ ",</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">             "/order/edit(d+)/ ",</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">         ]</span>
    <span style="color: #008000;">#</span><span style="color: #008000;">     }</span>
    <span style="color: #008000;">#</span><span style="color: #008000;"> }</span></pre>
    
    复制代码

       五、中间件
          - 在setting里设置白名单(不用权限就可以访问)

    复制代码
    #白名单
    VALID_URL = [
        "/login/",
        "/admin.*/",
        "/index/"
    ]
    

    # ====rabc
    PERMISSION_URL_DICT_KEY="permissions_url_dict"
    PERMISSION_MENU_KEY
    = "menu_list"

    复制代码
    复制代码
    MIDDLEWARE = [
        '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',
        'rbac.middlewears.rbac.Middle',
    ]
    复制代码


          - 获取当前的url请求
          - 获取session保存的权限信息

          - 循环url进行正则匹配,如果匹配成功就有权访问,不成功就无法访问

    用中间件的时候记得要在settings里面配置一下:

    复制代码
    #!usr/bin/env python
    # -*- coding:utf-8 -*-
    import re
    from django.shortcuts import render,HttpResponse,redirect
    from django.conf import settings
    class MiddlewareMixin(object):
        def __init__(self, get_response=None):
            self.get_response = get_response
            super(MiddlewareMixin, self).__init__()
    
    </span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__call__</span><span style="color: #000000;">(self, request):
        response </span>=<span style="color: #000000;"> None
        </span><span style="color: #0000ff;">if</span> hasattr(self, <span style="color: #800000;">'</span><span style="color: #800000;">process_request</span><span style="color: #800000;">'</span><span style="color: #000000;">):
            response </span>=<span style="color: #000000;"> self.process_request(request)
        </span><span style="color: #0000ff;">if</span> <span style="color: #0000ff;">not</span><span style="color: #000000;"> response:
            response </span>=<span style="color: #000000;"> self.get_response(request)
        </span><span style="color: #0000ff;">if</span> hasattr(self, <span style="color: #800000;">'</span><span style="color: #800000;">process_response</span><span style="color: #800000;">'</span><span style="color: #000000;">):
            response </span>=<span style="color: #000000;"> self.process_response(request, response)
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> response
    

    class Middle(MiddlewareMixin):
    def process_request(self,request):
    #获取当前的url请求
    current_url = request.path_info #拿到当前的路径
    # print(request.path,current_url)
    #获取Session中保存当前用户的权限,
    # request.session.get("permissions_url_list")
    # 如果当前的路径和session里面保存的url一样就break了,如果不一样就说明无权访问
    for url in settings.VALID_URL:
    # print(url,current_url)
    if re.match(url,current_url):
    return None #如果url是表名单白名单里面的,就让直接走后面的

        permission_dict </span>=<span style="color: #000000;"> request.session.get(settings.PERMISSION_URL_DICT_KEY)
        </span><span style="color: #008000;">#</span><span style="color: #008000;">在初始化的时候把url以字典的显示存在了session里面,现在获取的也就是一个字典了</span>
        <span style="color: #008000;">#</span><span style="color: #008000;"> print("==========",permission_dict)</span>
        flag =<span style="color: #000000;"> False
        </span><span style="color: #0000ff;">for</span> group_id,code_url <span style="color: #0000ff;">in</span><span style="color: #000000;"> permission_dict.items():
            </span><span style="color: #0000ff;">for</span> url <span style="color: #0000ff;">in</span> code_url[<span style="color: #800000;">"</span><span style="color: #800000;">urls</span><span style="color: #800000;">"</span><span style="color: #000000;">]:
                regax </span>= <span style="color: #800000;">"</span><span style="color: #800000;">^{0}$</span><span style="color: #800000;">"</span><span style="color: #000000;">.format(url)
                </span><span style="color: #008000;">#</span><span style="color: #008000;"> print(regax,current_url)</span>
                <span style="color: #0000ff;">if</span><span style="color: #000000;"> re.match(regax,current_url):
                    </span><span style="color: #008000;">#</span><span style="color: #008000;">match只要是..开头的都能匹配到,多以的加个^和$符</span>
                    request.permission_code_list=code_url[<span style="color: #800000;">"</span><span style="color: #800000;">codes</span><span style="color: #800000;">"</span><span style="color: #000000;">]
                    flag </span>=<span style="color: #000000;"> True
                    </span><span style="color: #0000ff;">break</span>
            <span style="color: #0000ff;">if</span> flag:  <span style="color: #008000;">#</span><span style="color: #008000;">跳出外层循环</span>
                <span style="color: #0000ff;">break</span>
        <span style="color: #0000ff;">if</span> <span style="color: #0000ff;">not</span><span style="color: #000000;"> flag:
            </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">无权访问</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    
    
    </span><span style="color: #0000ff;">def</span><span style="color: #000000;"> process_response(self,request,response):
        </span><span style="color: #0000ff;">return</span> response</pre>
    
    复制代码
  • 相关阅读:
    Mysql查询正在运行的事务
    linux SVN添加新用户
    linux下安装php扩展amqp
    解决apache启动错误:Could not reliably determine the server's fully qualified domain name
    linux系统安装redis服务器与php redis扩展
    navicat导出数据库字典
    centos安装GD库失败
    Mysql实现主从同步
    计算机的本质
    windows下nginx访问web目录提示403 Forbidden
  • 原文地址:https://www.cnblogs.com/maaosheng/p/11618768.html
Copyright © 2011-2022 走看看