• 2、rbac组件 后台布局模板,权限按钮,菜单,可拔插,路径重定向


    1、后台布局管理

    https://www.cnblogs.com/venicid/p/7772742.html#_label0

    1、通用模板

     overflow: auto;       //在a和b模板中进行切换

    a 模板 :左侧菜单跟随滚动条
     b模板  左侧以及上不动 ****
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>

    <style type="text/css"> .header { 100%; height: 60px; background-color: #369; } .right { float: right; } .left { float: left; } .menu { position: absolute; top: 60px; left: 0; bottom: 0; background-color: gainsboro; 20%; } .content { position: absolute; top: 60px; right: 0; bottom: 0; background-color: mediumpurple; 80%; overflow: auto; //在a和b模板中进行切换 } </style> </head> <body> <div class="header"></div> <div class="container"> <div class="menu left"> 1111 </div> <div class="content right">222 {% block content %} {% endblock %} </div> </div> </body> </html>

    2、模板继承

    users.html / roles.html 继承自 base.html

    users.html

    {% extends 'base.html' %}
    
    {% block con %}
    <h4>用户列表</h4>
        {% for user in user_list %}
        <p>{{ user }}</p>
        {% endfor %}
        
    {% endblock con%}

     2、权限按钮控制:简单控制

    用户权限不同,按钮显示就不同!

    登录成功后,就已经注册了session
    request.session['permission_list'] = permission_list

    permission_list = request.session.get('permission_list')

        简单控制:
            {% if "users/add" in permissions_list%} 

     3、修改表结构

    BUT: 不好,不想让 if "/users/add/" 写死,会有 "/roles/add/" 情况,不健壮!怎么办?      不应该根据表名,去判断!! 
    权限不同,按钮显示就不同 如何做呢?    
    上面问题的解决办法:
      为了扩展,
      # 把两条线 合成一个线
      /users/..
       /roles/...

    1、admin显示字段

    注意:list_display = []

    2、添加action,group字段

    注意点:
    加了一个权限组表,
    将每张表的增删改查,划到一个组里面!
    无论多复杂的,最终一定是对数据库的(增删改查)

    修改表结构,重新处理中间件,登录页面:
    目的:全是为了按钮的粒度,同一个模板,同一个视图,
    显示不同的数据,权限

     

    from django.db import models
    
    
    # Create your models here.
    
    class User(models.Model):
        name = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        roles = models.ManyToManyField(to='Role')
    
        def __str__(self):
            return self.name
    
    
    class Role(models.Model):
        title = models.CharField(max_length=32)
        permissions = models.ManyToManyField(to="Permission")
    
        def __str__(self):
            return self.title
    
    
    class Permission(models.Model):
        title = models.CharField(max_length=32)
        url = models.CharField(max_length=32)
        action = models.CharField(max_length=32, default="")
    
        group = models.ForeignKey(to="PermissionGroup", on_delete=True)
        def __str__(self):
            return self.title
    
    
    class PermissionGroup(models.Model):
         title = models.CharField(max_length=32 )
         def __str__(self):
             return self.title
    View Code

     

    4、重构数据结构

    1、登录验证

     

    2、构建permission_dict

    3.登录之后,重写 initial_session(user,request)
    就是:
    # 在session中注册权限列表 用户权限
    # request.session['permission_list'] = permission_list

    不应该是list 而是dict

    # 在session中注册权限字典
    request.session['permission_dict'] = permission_dict

     注意点:

    permission = user.roles.all().values('permission__url', 'permission__group_id', 'permission__action').distinct()

      对数据的处理,以组为键

    
    
    {1: {'urls': ['/users/', '/users/add/', '/users/delete/(\d+)/', '/users/edit/(\d+)/'], 
         'actions': ['list', 'add', 'delete', 'edit']}, 
     2: {'urls': ['/roles/'], 
         'actions': ['list']}}

    # -*- coding: utf-8 -*-
    # @Time    : 2018/08/11 0011 9:24
    # @Author  : Venicid
    
    
    def initial_session(request,user):
        # 方案2
        permissions = user.roles.all().values("permissions__url", "permissions__group_id","permissions__action").distinct()
        print(permissions)
        # <QuerySet [{'permissions__url': '/users/',
                    # 'permissions__group_id': 1,
                    # 'permissions__action': 'list'}]>
    
        permission_dict = {}
        for item in permissions:
            gid = item.get("permissions__group_id")
            if not gid in permission_dict:
                permission_dict[gid] = {
                    "urls":[item["permissions__url"],],
                    "actions":[item["permissions__action"],]
                }
            else:
                permission_dict[gid]["urls"].append(item["permissions__url"])
                permission_dict[gid]["actions"].append(item["permissions__action"])
    
        print(permission_dict)  # {1: {'urls': ['/users/'], 'actions': ['list']}}
        request.session["permission_dict"] = permission_dict
    
    
        # 方案1:
        """
        permissions = user.roles.all().values("permissions__url").distinct()
    
        permission_list = []
        for item in permissions:
            permission_list.append(item['permissions__url'])
    
        print(permission_list)  # ['/users/', '/users/add', '/users/delete/(\d+)', '/users/edit/(\d+)']
    
        request.session["permission_list"] = permission_list
        """
    
        """
        values :
    
        for role in user.roles.all():   # <QuerySet [<Role: 保洁>, <Role: 销售>]>
            temp.append({
            "title":role.title,
            "permissions_url":role.permissions.all()
            })
    
        # <QuerySet [{'title': '保洁', 'permissions__url': '/users/'},
        # {'title': '销售', 'permissions__url': '/users/'},
        # {'title': '销售', 'permissions__url': '/users/add'}]>
    
        """
    View Code

    5、限制权限粒度

    1、中间件校验权限:

        # 注意:妙 !!
    request.actions = item["actions"]

        

      

    # -*- coding: utf-8 -*-
    # @Time    : 2018/08/11 0011 9:04
    # @Author  : Venicid
    
    import re
    
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse, redirect
    
    
    class ValidPermission(MiddlewareMixin):
        def process_request(self, request):
    
            # 当前访问路径
            current_path = request.path_info
    
            # 1、检验是否属于白名单  白名单,不需要任何权限的url
            # 正则匹配
            valid_url_list = ['/login/', '/reg/', '/admin/.*']
            for valid_url in valid_url_list:
                ret = re.match(valid_url, current_path)
    
                if ret:
                    return None
    
            # 2、校验是否登录
            user_id = request.session.get("user_id")
            if not user_id:
                return redirect('/login/')
    
            # 3、校验权限2
    
            permission_dict = request.session.get("permission_dict", {})
            # {1: {'urls': ['/users/'], 'actions': ['list']}}
    
            for item in permission_dict.values():
                urls = item["urls"]
                for reg in urls:
                    reg = "^%s$" % reg
                    ret = re.match(reg, current_path)
                    if ret:
                        print("actions",item["actions"])
                        request.actions = item["actions"]
                        return None
            return HttpResponse("没有访问权限")
    
            # 3、校验权限1
            """
            permission_list = request.session.get("permission_list",[])
            print(permission_list)
    
            flag = False
            for permission in permission_list:
                permission = "^%s$" % permission
                # print(111111111,permission)
                # print(current_path)
                ret = re.match(permission, current_path)
                if ret:
                    flag = True
                    break
    
            if not flag:
                return HttpResponse("没有访问权限")
            return None
            """
    rbac中间件

    模板层,权限按钮控制

    2:用类来实现!!

    from django.shortcuts import render, HttpResponse
    
    # Create your views here.
    
    from rbac.models import *
    from rbac.service.perssions import *
    
    
    class Per(object):
        def __init__(self, actions):
            self.actions = actions
        def add(self):
            return "add" in self.actions
        def delete(self):
            return "delete" in self.actions
        def edit(self):
            return "edit" in self.actions
        def list(self):
            return "list" in self.actions
    
    
    def users(request):
        user_list = User.objects.all()
        permission_list = request.session.get("permission_list")
    
        # 查询当前登录人的名字
        id = request.session.get("user_id")
        user = User.objects.filter(id=id).first()
        print(user)
    
        per = Per(request.actions)
    
        return render(request, "users.html", locals())
    
    
    def add_user(request):
        return HttpResponse('add user')
    
    
    def delete_user(request, id):
        return HttpResponse('delete_user')
    
    
    def edit_user(request, id):
        return HttpResponse('edit_user')
    
    
    def roles(request):
        role_list = Role.objects.all()
    
        per = Per(request.actions)
        print(request.actions)
        return render(request, "roles.html", locals())
    
    
    def login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
    
            user = User.objects.filter(name=user, pwd=pwd).first()
            if user:
                ############## 在session中注册用户
                request.session['user_id'] = user.pk
    
                ############# 在session中注册权限list
                initial_session(request, user)
    
                return HttpResponse("登录成功")
    
        return render(request, 'login.html', locals())
    View

    3、效果

    不同的用户,具有不同的权限,

    权限不同,显示的按钮就不同!!

     

     6、权限不同,菜单显示不同

    只有查看,有必要放到菜单栏!
    即:action == list 放到 菜单栏中

    1.用户登录后,在initial_session中,注册菜单权限

      注意:permission__group__title 还可以这样用,跨了3张表!!

    # -*- coding: utf-8 -*-
    # @Time    : 2018/08/11 0011 9:24
    # @Author  : Venicid
    
    
    def initial_session(request,user):
        # 方案2
        permissions = user.roles.all().values("permissions__url", "permissions__group_id","permissions__action").distinct()
        print(permissions)
        # <QuerySet [{'permissions__url': '/users/',
                    # 'permissions__group_id': 1,
                    # 'permissions__action': 'list'}]>
    
        permission_dict = {}
        for item in permissions:
            gid = item.get("permissions__group_id")
            if not gid in permission_dict:
                permission_dict[gid] = {
                    "urls":[item["permissions__url"],],
                    "actions":[item["permissions__action"],]
                }
            else:
                permission_dict[gid]["urls"].append(item["permissions__url"])
                permission_dict[gid]["actions"].append(item["permissions__action"])
    
        print(permission_dict)  # {1: {'urls': ['/users/'], 'actions': ['list']}}
        request.session["permission_dict"] = permission_dict
    
    
        # 注册菜单权限
        permissions = user.roles.all().values("permissions__url", "permissions__action", "permissions__group__title").distinct()
    
        print(permissions)
        menu_permission_list = []
        for item in permissions:
            if item["permissions__action"] == "list":
                menu_permission_list.append((item["permissions__url"], item["permissions__group__title"]))
    
        print(menu_permission_list)   # [('/users/', '用户组'), ('/roles/', '角色组')]
        request.session["menu_permission_list"] = menu_permission_list
    
    
        # 方案1:
        """
        permissions = user.roles.all().values("permissions__url").distinct()
    
        permission_list = []
        for item in permissions:
            permission_list.append(item['permissions__url'])
    
        print(permission_list)  # ['/users/', '/users/add', '/users/delete/(\d+)', '/users/edit/(\d+)']
    
        request.session["permission_list"] = permission_list
        """
    
        """
        values :
    
        for role in user.roles.all():   # <QuerySet [<Role: 保洁>, <Role: 销售>]>
            temp.append({
            "title":role.title,
            "permissions_url":role.permissions.all()
            })
    
        # <QuerySet [{'title': '保洁', 'permissions__url': '/users/'},
        # {'title': '销售', 'permissions__url': '/users/'},
        # {'title': '销售', 'permissions__url': '/users/add'}]>
    
        """
    View Code

     2、menu

    可以实现,菜单显示!但是不行,为什么?

    因为模板继承,只继承样式,不继承数据!所有需要用到 自定义标签(inclusion_tag)

     3、自定义标签(inclusion_tag)

     

    # -*- coding: utf-8 -*-
    # @Time    : 2018/08/12 0012 16:11
    # @Author  : Venicid
    
    from django import template
    
    register = template.Library()
    
    
    @register.inclusion_tag("rbac/menu.html")
    def get_menu(request):
        # 获取当前用户可以放到菜单栏中的权限
        menu_permission_list = request.session.get("menu_permission_list")
    
        print(menu_permission_list)
    
        return {"menu_permission_list":menu_permission_list}
    View Code

    +

    7、可拔插配置:包...建在哪个App

        属于权限的就建在rbac的APP里,因为rpac最后是可插拔的组件!!

    users.html / roles.html / base.html / menu.html
    是和权限相关的,所以应该放在 rbac/templates/... 方便以后copy走!!

    djangod的render去渲染 .html 时,先到项目的 templates 下找,找不到,再到App下 templates 下找,
    最后找不到,才报错!!

      

     如果多个App的templates 下的.html重名怎么办? django 会根据注册的顺序显示!
    解决办法:
    项目/rbac/templates/rbac/xxx.html

    这时调用:
    return render(request, 'rbac/users.html', locals())

    注意:
    templates 或者 templatetag 注意多个app下面 的文件名 有可能都会重名!!
    办法:就是 eg:/rbac/templates/rbac/xxx.html 或者不起重名

    注意:
    如果 base.html 在项目下有,在App下有,先找项目下的,找不到才找App
    全局可以覆盖局部的!!

     8、路径自动添加

    知识点:路径自动添加问题:
    http://127.0.0.1:8010/users
    http://127.0.0.1:8010/users/

    浏览器发请求:
    django 发现之后,发了一个重定向的 url 加了一个 /
    所有才能匹配上:
    path('users/', views.users),

    如何让django不给浏览器发重定向,不加 /
    配置:
    APPEND_SLASH = False

    APPEND_SLASH = True # 默认为 True

    ajax 也是,django会默认的加 / 发重定向

    1、django浏览器重定向

     2、APPEND_SLASH = False

      ajax 也是,django会默认的加 / 发重定向

     9、github代码

    https://github.com/venicid/rbac

  • 相关阅读:
    几维安全SDK应用加固,全线5折为APP保驾护航
    物联网渗透测试威胁建模,捕捉应用相关安全风险
    【几维安全】Android代码混淆,代码混淆工具,Android版使用详细说明
    畅想物联网安全未来,几维安全让万物互联更安全
    域起网络携手几维安全,护航互联网游戏业务安全
    Android 加密, Android 常用加密, Android So 库高强度加密
    车联网安全威胁分析及防护思路,几维安全为智能汽车保驾护航
    C#实现基于ffmpeg加虹软的人脸识别
    OSX 下搭建Asp.Net vNext的开发环境
    验证码识别记录
  • 原文地址:https://www.cnblogs.com/venicid/p/9462452.html
Copyright © 2020-2023  润新知