python编程-权限管理

一:表结构(共八张表)


from django.db import models


# Create your models here.
class User(models.Model):
username = models.CharField(max_length=32)
pasword = models.CharField(max_length=32)
class Meta:
verbose_name_plural = "用户表"
def __str__(self):
return self.username


class Role(models.Model):
caption = models.CharField(max_length=32)
class Meta:
verbose_name_plural = "角色表"
def __str__(self):
return self.caption


class User2Role(models.Model):
u = models.ForeignKey("User")
r = models.ForeignKey("Role")


class Meta:
verbose_name_plural = "用户角色分配表"
def __str__(self):
return "%s:%s"%(self.u.username,self.r.caption)


class Action(models.Model):
#/user.html?t=get 获取用户信息
#/user.html?t=post 创建用户
#/user.html?t=put 修改用户
#/user.html?t=delete 删除用户


#1 ---> get 查询
#2 ---> post 增加
#3 ---> put 修改
#4 ---> delete 删除
caption = models.CharField(max_length=32)
code = models.CharField(max_length=32)


class Meta:
verbose_name_plural = "操作表"
def __str__(self):
return self.caption


class Menu(models.Model):
caption = models.CharField(max_length=32)
parent = models.ForeignKey("self",related_name="p",null=True,blank=True)


class Meta:
verbose_name_plural="菜单表"
def __str__(self):
return self.caption


class Permission(models.Model):
#/user.html 用户管理
caption = models.CharField(max_length=32)
url = models.CharField(max_length=32)
menu = models.ForeignKey("Menu",null=True)


class Meta:
verbose_name_plural = "权限"


def __str__(self):
return self.caption


class Permission2Action(models.Model):
p = models.ForeignKey("Permission")
a = models.ForeignKey("Action")


class Meta:
verbose_name_plural = "权限表"
def __str__(self):
return "%s-%s:%s?t=%s"%(self.p.caption,self.a.caption,self.p.url,self.a.code)



class Permission2Action2Role(models.Model):
p2a = models.ForeignKey("Permission2Action")
r = models.ForeignKey("Role")


class Meta:
verbose_name_plural = "角色权限分配表"
def __str__(self):
return "%s:%s"%(self.r.caption,self.p2a)

 

二:登录业务

def login(request):
    if request.method == "GET":
        return render(request,"login.html")
    else:
        username = request.POST.get("username")
        pasword = request.POST.get("password")
        obj = models.User.objects.filter(username=username,pasword=pasword).get()
        if obj:
            #获取用户信息,放在session中
            request.session[‘user_info‘] = {‘nid‘:obj.id,‘username‘:obj.username}

            #获取所有权限
            #获取在菜单中显示的权限
            #获取所有菜单
            #放置在session
            MenuHelper(request,username)
            return redirect(‘/index.html‘)
        else:
            return redirect(‘/login.html‘)

三:权限类生成(进行权限和菜单的业务处理)

class MenuHelper(object):
    def __init__(self,request,username):
        #当前请求的request
        self.request = request
        #当前用户名
        self.username = username
        #获取当前url
        self.current_url = request.path_info

        #获取当前用户的所有权限
        self.permission2action_dict = {}   #{‘url‘:["操作列表"],}
        #菜单的叶子节点,即:菜单的最后一层应该(含有权限url)显示的权限,对应上面的permission2action_dict
        self.menu_leaf_list = []
        #获取所有菜单对象
        self.menu_list = []

        #初始化数据,将数据放入session中
        self.session_data()

    #注:只进行数据处理(数据最后是基础类型),不进行业务逻辑(目标就是将数据放在session中)
    def session_data(self):
        #(0)先在session中查看数据是否已经存在
        permission_dict = self.request.session.get("permission_info")
        if permission_dict:
            self.permission2action_dict = permission_dict[‘permission2action_dict‘]
            self.menu_leaf_list = permission_dict[‘menu_leaf_list‘]
            self.menu_list = permission_dict[‘menu_list‘]
            return

        #获取所有角色
        r_list = models.Role.objects.filter(user2role__u__username=self.username).all()
        #获取角色下的所有权限操作,存放方式{‘url‘:["操作列表"],}便于查找   --> 例如  {‘user.html‘:[‘get‘,‘post‘],}
        p2a_list = models.Permission2Action.objects.filter(permission2action2role__r__in=r_list)
        #权限操作去重,使用集合去重
        p2a_list = set(p2a_list)

        #(1)循环权限操作列表,将其变为{‘user.html‘:[‘get‘,‘post‘],}格式,然后加入self.permission2action_dict
        for p2a in p2a_list:
            # print(p2a.p.url)
            if self.permission2action_dict.get(p2a.p.url) == None:
                self.permission2action_dict[p2a.p.url] = []
            self.permission2action_dict[p2a.p.url].append(p2a.a.code)

        #上面是用户拥有的所有权限,用于权限校验,下面这个是显示在菜单最后一层的权限(也只有最后一层才会有url权限)

        #(2)获取菜单的叶子节点,即:菜单的最后一层应该显示的权限
        self.menu_leaf_list = list(
            models.Permission2Action.objects.             filter(permission2action2role__r__in=r_list).exclude(p__menu__isnull=True).             values(‘p_id‘,‘p__url‘,‘p__caption‘,‘p__menu‘).distinct()
        )

        #(3)获取所有的菜单全部,(根据上面的菜单叶子节点,以及下面的所有菜单,进行比较,我们可以获取到所有应该显示的菜单)
        self.menu_list = list(models.Menu.objects.values(‘id‘,‘caption‘,‘parent_id‘))

        #(4)将上面获取的数据,放入session中
        self.request.session[‘permission_info‘] = {
            ‘permission2action_dict‘:self.permission2action_dict,
            ‘menu_leaf_list‘:self.menu_leaf_list,
            ‘menu_list‘:self.menu_list,
        }

    #生成菜单树形结构(包括其他数据)
    def menu_data_list(self):
        menu_leaf_dict = {}
        #形式
        # {
        #     ‘父id‘:[‘子节点‘,‘子节点‘,],
        #     ‘父id‘:[‘子节点‘,‘子节点‘,]
        # }

        open_leaf_parent_id = None

        #(1)归并所有叶子节点
        for item in self.menu_leaf_list:
            item = {
                ‘id‘:item[‘p_id‘],
                ‘url‘:item[‘p__url‘],
                ‘caption‘:item[‘p__caption‘],
                ‘parent_id‘:item[‘p__menu‘],    #对应的是菜单id,可以看出,每个叶子节点都是挂在菜单节点下面,我们只需获取菜单的树形结构,将权限叶子节点挂载上去就可以
                ‘child‘:[],
                ‘status‘:True,  #是否显示
                ‘open‘:False    #是否展开
            }

            if item[‘parent_id‘] in menu_leaf_dict:
                menu_leaf_dict[item[‘parent_id‘]].append(item)
            else:
                menu_leaf_dict[item[‘parent_id‘]] = [item,]
            if re.match(item[‘url‘],self.current_url):  #若是当前访问的url,则打开
                item[‘open‘] = True
                open_leaf_parent_id = item[‘parent_id‘]

        #(2)获取所有菜单字典
        menu_dict = {}
        #形式也是
        # {
        #     ‘菜单id‘:‘对应数据处理的字典‘,
        #     ‘菜单id‘: ‘对应数据处理的字典‘,
        #     ‘菜单id‘: ‘对应数据处理的字典‘,
        # }

        for item in self.menu_list:
            item[‘child‘] = []
            item[‘status‘] = False  #是否显示,只有拥有权限的菜单,才会展示给用户,其他的不会显示
            item[‘open‘] = False    #和权限叶子节点一致,展开就是一级一级显示,其他闭合

            menu_dict[item[‘id‘]] = item

        #根据上面的全部菜单和归并后的叶子节点一起获取我们真正需要的菜单

        #(3)将叶子节点添加到菜单中
        for k,v in menu_leaf_dict.items():
            menu_dict[k][‘child‘] = v       #为菜单挂载上权限叶子节点
            parent_id = k
            while parent_id:    #当权限子节点存在,则其父级会向上全部显示
                menu_dict[parent_id][‘status‘] = True
                parent_id = menu_dict[parent_id][‘parent_id‘]

        #(4)将菜单中已经选中的菜单标记为展开(一级一级展开)
        while open_leaf_parent_id:
            menu_dict[open_leaf_parent_id][‘open‘] = True
            open_leaf_parent_id = menu_dict[open_leaf_parent_id][‘parent_id‘]

        #(5)对所有菜单,进行树形结构生成,不需要考虑其他的因素(例如是否是叶子节点,是否有权限)
        #我们只需要判断状态status是否为True,然后筛选即可

        result = []
        for row in menu_dict.values():  #所有菜单进行树形排序
            if not row[‘parent_id‘]:
                result.append(row)  # 注意:基础-->列表赋值的时候默认是浅拷贝,所以无论是是么时候添加到result中,后面的操作对于result数据也是有效d的
            else:
                menu_dict[row[‘parent_id‘]][‘child‘].append(row)

        #(6)返回树形结构
        return result

    #获取子菜单列表的子菜单列表(递归模式)
    def menu_content(self,child_list):
        response = ""
        # 菜单模板HTML
        tpl = """
            <div class="item %s">
                <div class="title">%s</div>
                <div class="content">%s</div>
            </div>
        """
        for row in child_list:
            if not row[‘status‘]:
                continue
            active = ""
            if row[‘open‘]:
                active = "active"
            if ‘url‘ in row:
                response += "<a class=‘%s‘ href=‘%s‘>%s</a>"%(active,row[‘url‘],row[‘caption‘])
            else:
                title = row[‘caption‘]
                content = self.menu_content(row[‘child‘])
                response += tpl % (active,title,content)
        return  response

    def menu_tree(self):
        response = ""
        # 菜单模板HTML
        tpl = """
            <div class="item %s">
                <div class="title">%s</div>
                <div class="content">%s</div>
            </div>
        """

        for row in self.menu_data_list():   #获取函数返回的树形结构,进行HTML处理,这里全是根目录菜单
            if not row[‘status‘]:   #对于不需要显示的,不做处理
                continue
            active = ""
            if row[‘open‘]: #对于展开的,我们要设置其状态为active
                active = "active"
            title = row[‘caption‘]

            #获取其子代的HTML,放在content中
            content = self.menu_content(row[‘child‘])   #默认子代是列表
            response += tpl % (active,title,content)

        return response

    def actions(self):
        ‘‘‘
        检测当前用户是否对当前url有权限访问,并获取对当前url有什么权限
        :return:
        ‘‘‘
        action_list = []
        #当前数据中保存的权限是{‘user.html‘:[‘get‘,‘post‘],}格式,在self.permission2action_dict中
        for k,v in self.permission2action_dict.items():
            if re.match(k,self.current_url):
                action_list = v
                break

        return action_list

四:生成装饰器(用于用户的验证,使用了上面类)

#设置装饰器
def permission(func):
    def inner(request,*args,**kwargs):
        user_info = request.session.get(‘user_info‘)
        if not user_info:
            return redirect("/login.html")
        obj = MenuHelper(request,user_info[‘username‘])
        action_list = obj.actions()
        if not action_list:
            return HttpResponse("无权限访问")
        kwargs[‘menu_string‘] = obj.menu_tree()
        kwargs[‘action_list‘] = action_list

        return func(request,*args,**kwargs)
    return inner

五:装饰器使用

@permission
def index(request,*args,**kwargs):
    acion_list = kwargs.get(‘action_list‘)
    menu_string = kwargs.get("menu_string")

    if str(request.method).lower() in acion_list:
        result = "数据,可以访问"
    else:
        result = "没有数据,无权限访问"

    return render(request,‘index.html‘,{‘menu_string‘:menu_string,‘action_list‘:acion_list,‘result‘:result})

六:退出业务

def logout(request):
    request.session.clear()
    return redirect(‘/login.html‘)

七:前台模板,以及效果展示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .item{
            margin-left: 24px;
        }
        .item a{
            margin-left: 24px;
        }
    </style>
</head>
<body>
    <div>
        <span>菜单显示</span>
        {{ menu_string|safe }}
    </div>
    <div>
        <span>结果数据</span>
        {{ result }}
    </div>
</body>
</html>

原帖地址:https://www.cnblogs.com/ssyfj/p/8964912.html

原文地址:https://www.cnblogs.com/gx8900/p/9260577.html

时间: 2024-08-30 13:22:14

python编程-权限管理的相关文章

ASP.NET MVC+EF框架+EasyUI实现权限管理系列(3)-面向接口的编程

原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(3)-面向接口的编程 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)  (1)框架搭建    (2):数据库访问层的设计Demo 前言:这篇博客在数据访问层的基础上面我们继续学习对这个Demo的开发,希望大家都好好理解一下这个Demo的架构,到最后我实现权限的时候我就简单的说一下搭建过程就OK了,因为这个Demo的思想就是按照权限的设计方式去设计的,下面我们开始介绍面向接口的编程思想,如果感觉好的话可以

MongoDB的账户与权限管理及在Python与Java中的登录

本文主要介绍了MongoDB的账户新建,权限管理(简单的),以及在Python,Java和默认客户端中的登陆. 默认的MongoDB是没有账户权限管理的,也就是说,不需要密码即可登陆,即可拥有读写的权限(当然,重启服务还是需要在本机执行).这个对于自己做实验室足够使用的,但是对于开放数据给他人使用时很不安全的,倒不是怕窃取数据,主要是怕某些猪队友一下把db给drop了,如果没有容灾备份哭都来不及.对于MongoDB的权限配置,我看着官方文档和别人的笔记也算是踩过坑的人了,把踩过的坑写出来给大家看

搞定linux上MySQL编程(四):mysql权限管理

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] mysql中提供了比较完整的安全/权限管理系统,下面简单介绍权限的原理和使用. mysql数据库安装完成启动之后,能看当前数据库列表可以看到一个mysql的数据库: mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | |

权限管理2 以及bash的特性 快捷键,补全功能以及变量的类型,登录类型,脚本

权限管理: owner          group         other 属主              属组            其它 权限:read   write     execute r           w            x 文件: -r:可以使用文件查看类的命令来显示相关内容 -w:可以使用编辑器修改内容 -x:可以将其发起一个进程 目录: -r:可以使用ls命令查看目录内容的的文件信息 -w:可以创建 删除文件 -x:可以使用ls -l命令查看内容的文件信息,

8.python之上下文管理协议

使用上下文管理协议,有什么好处? 使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预. 在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处. 之前所提到的with代码块,就是python的上下文管理操作,比如说通过python打开一个文件,就可以通过with代码块结合open去实现,通过这种方式打开的文件,执行了相应的操作后,无需我们手动去close文件,文件

ASP.NET MVC+EF框架+EasyUI实现权限管理系列

http://www.cnblogs.com/hanyinglong/archive/2013/03/22/2976478.html ASP.NET MVC+EF框架+EasyUI实现权限管理系列之开篇 前言:博客又有一段时间没有更新了,心里感觉这段时间空空的,好像什么都没有学下,所以就想写博客,所以就有了这个系列,这里当然也要感谢大家了,因这个 项目我已经上传了,得到了很多网友的评价,也有好多人发邮件给我说这个框架容易出现问题,不能访问,这也是支持我写这个系列的动力,我将这个项目写成一个 系列

如何使用php设计权限管理数据库

很多网站管理员都想获得php权限,admin,或者root.但如何使用php设置管理员数据库呢? 万事开头难,这里介绍一下. 首先在B/S系统中的权限比C/S中的更显的重要,C/S系统因为具有特殊的客户端,所以访问用户的权限检测可以通过客户端实现或通过客户端+服务器检测实现,而B/S中,浏览器是每一台计算机都已具备的,如果不建立一个完整的权限检测,那么一个"非法用户"很可能就能通过浏览器轻易访问到B/S系统中的所有功能.因此B/S业务系统都需要有一个或多个权限系统来实现访问权限检测,让

[转载] python的内存管理机制

本文为转载,原作为http://www.cnblogs.com/CBDoctor/p/3781078.html,请大家支持原作者 先从较浅的层面来说,Python的内存管理机制可以从三个方面来讲 (1)垃圾回收 (2)引用计数 (3)内存池机制 一.垃圾回收: python不像C++,Java等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值.对Python语言来讲,对象的类型和内存都是在运行时确定的.这也是为什么我们称Python语言为动态类型的原因(这里我们把动态类型可以简单的归结

【Linux】 Linux权限管理与特殊权限

Linux权限管理 权限管理这方面,非常清楚地记得刚开始实习那会儿是仔细研究过的,不知道为什么没有笔记留痕..除了一些基本的知识点早就忘光了,无奈只好从头开始学习一遍.. ■ 基本权限知识 这部分实在是比较基础,不想多讲了.主要就是9格权限的理解.搞清楚读权限.写权限和执行权限对于文件和目录来说分别以为着什么,就可以了.下面是一些以前没怎么注意,今天听完培训之后觉得有些意思的点: ●  管理权限的权限 文件权限信息和其他文件信息一样,并不属于文件内容的一部分,而基本的权限是针对文件内容而言的.比