用户角色权限 案例
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用户角色权限 案例相关的知识,希望对你有一定的参考价值。
一. 权限用户表
a. SQL表结构
from django.db import models class User(models.Model): """ 用户表 """ username = models.CharField(verbose_name=\'用户名\', max_length=32) password = models.CharField(verbose_name=\'密码\', max_length=64) email = models.EmailField(verbose_name=\'邮箱\') def __str__(self): return self.username class Role(models.Model): """ 角色表 """ caption = models.CharField(verbose_name=\'角色\', max_length=32) def __str__(self): return self.caption class User2Role(models.Model): """ 用户角色关系表 """ user = models.ForeignKey(User, verbose_name=\'用户\', related_name=\'roles\') role = models.ForeignKey(Role, verbose_name=\'角色\', related_name=\'users\') def __str__(self): return \'%s-%s\' % (self.user.username, self.role.caption,) class Menu(models.Model): """ 菜单表 """ caption = models.CharField(verbose_name=\'菜单名称\', max_length=32) parent = models.ForeignKey(\'self\', verbose_name=\'父菜单\', related_name=\'p\', null=True, blank=True) def __str__(self): prev = "" parent = self.parent while True: if parent: prev = prev + \'-\' + str(parent.caption) parent = parent.parent else: break return \'%s-%s\' % (prev, self.caption,) class Permission(models.Model): """ 权限 """ caption = models.CharField(verbose_name=\'权限\', max_length=32) url = models.CharField(verbose_name=\'URL正则\', max_length=128) menu = models.ForeignKey(Menu, verbose_name=\'所属菜单\', related_name=\'permissions\',null=True,blank=True) def __str__(self): return "%s-%s" % (self.caption, self.url,) class Action(models.Model): """ 操作:增删改查 """ caption = models.CharField(verbose_name=\'操作标题\', max_length=32) code = models.CharField(verbose_name=\'方法\', max_length=32) def __str__(self): return self.caption class Permission2Action2Role(models.Model): """ 权限操作关系表 """ permission = models.ForeignKey(Permission, verbose_name=\'权限URL\', related_name=\'actions\') action = models.ForeignKey(Action, verbose_name=\'操作\', related_name=\'permissions\') role = models.ForeignKey(Role, verbose_name=\'角色\', related_name=\'p2as\') class Meta: unique_together = ( (\'permission\', \'action\', \'role\'), ) def __str__(self): return "%s-%s-%s" % (self.permission, self.action, self.role,) python3 manage.py startapp app02
b. 输出菜单
urlpatterns = [ url(r\'^app02_test.html\', views2.app02_test), ]
from django.contrib import admin # Register your models here. from app02 import models admin.site.register(models.User) admin.site.register(models.Role) admin.site.register(models.User2Role) admin.site.register(models.Menu) admin.site.register(models.Permission) admin.site.register(models.Action) admin.site.register(models.Permission2Action2Role)
def app02_test(request): """ 需要用户名或用户ID,产出:用户关联所有菜单 :param request: :return: """ # 所有菜单:处理成当前用关联的菜单 all_menu_list = models.Menu.objects.all().values(\'id\', \'caption\', \'parent_id\') """ [ {\'id\':1, \'caption\':\'菜单1\', parent_id:None}, {\'id\':2, \'caption\':\'菜单2\', parent_id:None}, {\'id\':3, \'caption\':\'菜单3\', parent_id:None}, {\'id\':4, \'caption\':\'菜单1-1\', parent_id:1}, ] { 1:{\'id\':1, \'caption\':\'菜单1\', parent_id:None,status:False,opened:False,child:[]}, 2:{\'id\':2, \'caption\':\'菜单2\', parent_id:None,status:False,opened:False,child:[]}, 3:{\'id\':3, \'caption\':\'菜单3\', parent_id:None,status:False,opened:False,child:[]}, 5:{\'id\':4, \'caption\':\'菜单1-1\', parent_id:1,status:False,opened:False,child:[]}, } """ user = models.User.objects.filter(username=\'alex\').first() role_list = models.Role.objects.filter(users__user=user) permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values(\'permission__id\', \'permission__url\', \'permission__menu_id\', \'permission__caption\').distinct() """ [ {\'permission__url\':\'/order.html\',\'permission__caption\': \'订单管理\',\'permission__menu_id\': 1 }, {\'permission__url\':\'/order.html\',\'permission__caption\': \'订单管理\',\'permission__menu_id\': 2 }, {\'permission__url\':\'/order.html\',\'permission__caption\': \'订单管理\',\'permission__menu_id\': 3 }, {\'permission__url\':\'/order.html\',\'permission__caption\': \'订单管理\',\'permission__menu_id\': 4 }, ] """ ##### 将权限挂靠到菜单上 ######## all_menu_dict = {} for row in all_menu_list: row[\'child\'] = [] # 添加孩子 row[\'status\'] = False # 是否显示菜单 row[\'opened\'] = False # 是否默认打开 all_menu_dict[row[\'id\']] = row for per in permission_list: if not per[\'permission__menu_id\']: continue item = { \'id\': per[\'permission__id\'], \'caption\': per[\'permission__caption\'], \'parent_id\': per[\'permission__menu_id\'], \'url\': per[\'permission__url\'], \'status\': True, \'opened\': False } # print(item["url"]) if re.match(per[\'permission__url\'],request.path_info): # if re.match(per[\'permission__url\'], "/orders.html"): item[\'opened\'] = True pid = item[\'parent_id\'] all_menu_dict[pid][\'child\'].append(item) # 将当前权限前辈status=True temp = pid # 1.父亲ID while not all_menu_dict[temp][\'status\']: all_menu_dict[temp][\'status\'] = True temp = all_menu_dict[temp][\'parent_id\'] if not temp: break # 将当前权限前辈opened=True if item[\'opened\']: temp1 = pid # 1.父亲ID while not all_menu_dict[temp1][\'opened\']: all_menu_dict[temp1][\'opened\'] = True temp1 = all_menu_dict[temp1][\'parent_id\'] if not temp1: break # ############ 处理菜单和菜单之间的等级关系 ############ """ all_menu_dict = { 1:{\'id\':1, \'caption\':\'菜单1\', parent_id:None,status:False,opened:False,child:[{\'permission__url\':\'/order.html\',\'permission__caption\': \'订单管理\',\'permission__menu_id\': 1 },]}, 2:{\'id\':2, \'caption\':\'菜单2\', parent_id:None,status:False,opened:False,child:[]}, 3:{\'id\':3, \'caption\':\'菜单3\', parent_id:None,status:False,opened:False,child:[]}, 5:{\'id\':4, \'caption\':\'菜单1-1\', parent_id:1,status:False,opened:False,child:[]}, } all_menu_list= [ {\'id\':1, \'caption\':\'菜单1\', parent_id:None,status:False,opened:False,child:[{\'permission__url\':\'/order.html\',\'permission__caption\': \'订单管理\',\'permission__menu_id\': 1 }, {\'id\':4, \'caption\':\'菜单1-1\', parent_id:1,status:False,opened:False,child:[]},]}, {\'id\':2, \'caption\':\'菜单2\', parent_id:None,status:False,opened:False,child:[]}, {\'id\':3, \'caption\':\'菜单3\', parent_id:None,status:False,opened:False,child:[]}, ] """ result = [] for row in all_menu_list: pid = row[\'parent_id\'] if pid: all_menu_dict[pid][\'child\'].append(row) else: result.append(row) ##################### 结构化处理结果 ##################### # print(result) # for row in result: # # print(row[\'caption\'], row[\'status\'], row[\'opened\'], ) # print(row) ##################### 通过结构化处理结果,生成菜单开始 ##################### def menu_tree(menu_list): tpl1 = """ <div class=\'menu-item\'> <div class=\'menu-header\'>{0}</div> <div class=\'menu-body {2}\'>{1}</div> </div> """ tpl2 = """ <a href=\'{0}\' class=\'{1}\'>{2}</a> """ menu_str = "" for menu in menu_list: if not menu[\'status\']: continue # menu: 菜单,权限(url) if menu.get(\'url\'): # 权限 menu_str += tpl2.format(menu[\'url\'],\'active\' if menu[\'opened\'] else "",menu[\'caption\']) else: # 菜单 if menu[\'child\']: child_html = menu_tree(menu[\'child\']) else: child_html = "" menu_str += tpl1.format(menu[\'caption\'], child_html,"" if menu[\'opened\'] else \'hide\') return menu_str menu_html = menu_tree(result) return render(request, "menu_html.html", {"menu_html":menu_html})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .menu-body{ margin-left: 20px; } .menu-body a{ display: block; } .menu-body a.active{ color: red; } .hide{ display: none; } </style> </head> <body> {{ menu_html|safe }} <script src="/static/jquery-3.2.1.js"></script> <script> $(function () { $(".menu-header").click(function () { $(this).next().removeClass("hide").parent().siblings().find(".menu-body").addClass("hide") }) }) </script> </body> </html>
c. result 结果递归 debug调试
result = [ {\'opened\': True, \'parent_id\': None, \'caption\': \'菜单一\', \'id\': 1, \'status\': True, \'child\': [ {\'opened\': False, \'parent_id\': 1, \'caption\': \'帅哥管理\', \'id\': 5, \'status\': True, \'url\': \'/shuaige.html\'}, {\'opened\': True, \'parent_id\': 1, \'caption\': \'菜单一 一\', \'id\': 4, \'status\': True, \'child\': [ {\'opened\': True, \'parent_id\': 4, \'caption\': \'用户管理\', \'id\': 1, \'status\': True, \'url\': \'/users.html\'}, {\'opened\': False, \'parent_id\': 4, \'caption\': \'订单管理\', \'id\': 2, \'status\': True, \'url\': \'/orders.html\'} ] }, {\'opened\': False, \'parent_id\': 1, \'caption\': \'菜单一 二\', \'id\': 5, \'status\': False, \'child\': []}, {\'opened\': False, \'parent_id\': 1, \'caption\': \'菜单一 三\', \'id\': 6, \'status\': False, \'child\': []} ] }, {\'opened\': False, \'parent_id\': None, \'caption\': \'菜单二\', \'id\': 2, \'status\': False, \'child\': []}, {\'opened\': False, \'parent_id\': None, \'caption\': \'菜单三\', \'id\': 3, \'status\': False, \'child\': []} ]
result = [{\'opened\': True, \'parent_id\': None, \'caption\': \'菜单一\', \'id\': 1, \'status\': True, \'child\': [{\'opened\': False, \'parent_id\': 1, \'caption\': \'帅哥管理\', \'id\': 5, \'status\': True, \'url\': \'/shuaige.html\'}, {\'opened\': True, \'parent_id\': 1, \'caption\': \'菜单一 一\', \'id\': 4, \'status\': True, \'child\': [{\'opened\': True, \'parent_id\': 4, \'caption\': \'用户管理\', \'id\': 1, \'status\': True, \'url\': \'/users.html\'}, {\'opened\': False, \'parent_id\': 4, \'caption\': \'订单管理\', \'id\': 2, \'status\': True, \'url\': \'/orders.html\'}]}, {\'opened\': False, \'parent_id\': 1, \'caption\': \'菜单一 二\', \'id\': 5, \'status\': False, \'child\': []}, {\'opened\': False, \'parent_id\': 1, \'caption\': \'菜单一 三\', \'id\': 6, \'status\': False, \'child\': []}]}, {\'opened\': False, \'parent_id\': None, \'caption\': \'菜单二\', \'id\': 2, \'status\': False, \'child\': []}, {\'opened\': False, \'parent_id\': None, \'caption\': \'菜单三\', \'id\': 3, \'status\': False, \'child\': []}] def menu_tree(menu_list): tpl1 = """ <div class=\'menu-item\'> <div class=\'menu-header\'>{0}</div> <div class=\'menu-body {2}\'>{1}</div> </div> """ tpl2 = """ <a href=\'{0}\' class=\'{1}\'>{2}</a> """ menu_str = "" for menu in menu_list: if not menu[\'status\']: continue # menu: 菜单,权限(url) if menu.get(\'url\'): # 权限 menu_str += tpl2.format(menu[\'url\'], \'active\' if menu[\'opened\'] else "", menu[\'caption\']) print("***", menu_str) else: # 菜单 if menu[\'child\']: child_html = menu_tree(menu[\'child\']) print("----", child_html) else: child_html = "" print("111") menu_str += tpl1.format(menu[\'caption\'], child_html, "" if menu[\'opened\'] else \'hide\') print("AAAAA", menu_str) print(123) return menu_str menu_html = menu_tree(result) print("xx", menu_html)
二. 组件
生成公共app - 权限限制 - 生成菜单
python3 manage.py startapp rbac
#白名单url, 不验证
VALID_URL = [
\'/app01/.*\',
\'/app02/.*\'
\'/login.html\'
\'/logout.html\'
]
from django.db import models class User(models.Model): """ 用户表 """ username = models.CharField(verbose_name=\'用户名\', max_length=32) password = models.CharField(verbose_name=\'密码\', max_length=64) email = models.EmailField(verbose_name=\'邮箱\') def 以上是关于用户角色权限 案例的主要内容,如果未能解决你的问题,请参考以下文章登录综合案例03,分配角色,分配权限,前端使用vue+elementui+axios 后端 springboot+mybatis-plus+swagger2
Android 逆向Linux 文件权限 ( Linux 权限简介 | 系统权限 | 用户权限 | 匿名用户权限 | 读 | 写 | 执行 | 更改组 | 更改用户 | 粘滞 )(代码片段