Winform开发框架之权限管理系统的改进

权限管理系统,一直是很多Mis系统和一些常见的管理系统所需要的,所以一般可以作为独立的模块进行开发,需要的时候进行整合即可,不需要每次从头开发,除非特殊的系统需求。我在Winform开发框架介绍中的随笔中,很早之前在《Winform开发框架之权限管理系统》就写过关于我的通用权限管理系统的一些介绍,当时这个版本的还是传统样式的,界面如下所示。

 

由于我的Winform开发框架需要,我把权限管理系统、字典管理模块、分页控件等都扩展了支持传统样式、DotNetBar控件样式,以及DevExpress控件样式。这些样式的界面之前也已经介绍不少了,本文主要介绍使用DevExpress控件样式的权限管理系统,对一些新的功能扩展以及完善,包括系统类型管理、菜单管理、功能管理、登陆日志管理等模块进行介绍。

本权限管理系统包括用户管理、组织机构管理、角色管理、系统类型定义、功能管理、菜单管理、用户登录日志管理,以及对相应对象的权限控制管理等功能。整个权限管理系统是基于RBAC(基于角色的访问控制)方式进行权限控制,是一个独立的权限管理系统,需要的时候业务系统与之进行整合即可,实现通用模块的高效利用和统一管理等方面。

1、系统类型管理

系统类型,是我们在权限系统中定义的一个系统分类,对于不同的系统,我们通过这个定义进行区分,可以实现多个业务系统的管理(虽然一般情况下,我们只是管理一个系统)。系统类型管理界面如下所示。

这个对象的管理,以前一直在权限系统中,通过修改数据库进行初始化,不过我觉得把它作为一个独立的数据进行维护,然后为功能定义、菜单、登陆日志等和系统类型关联的数据进行设置管理,应该是比较方便的。

因为,功能定义是基于某个系统而增加的一系列功能控制ID的定义,方便实现按钮级别和数据级别的权限控制的基础。

菜单的定义,是用来实现基于动态配置功能模块的菜单,引入该模块的初衷是用来方便动态配置Winform或者Web的功能菜单,这个也是不同的系统肯定有不同的菜单了。

登陆日志管理,是用来方便记录来自业务系统对权限系统接口的重要接口调用的记录,如登陆、修改密码等操作,一般情况下,我们用不同的业务系统来区分它们的数据。

2、菜单管理

刚才说到,这里的菜单管理,是指用来实现基于动态配置功能模块的菜单,用来实现基于Winform、Web菜单的集成统一,对于不同的系统,菜单定义是不同的,因此他们是基于某个系统类型下面的数据管理。

为了有效管理菜单数据,我把菜单的关系用树形控件进行展示,并通过SplitContainer控件实现布局的合理切分,可以实现自由拖动,界面效果如下所示。

菜单的数据显示,左边使用了树形控件,数据通过递归方式进行绑定。右边数据是通过我的分页控件进行数据绑定,并且绑定的数据是通过了层级的缩进格式化了的。

树菜单绑定的核心递归代码如下所示。

        /// <summary>
        /// 绑定树形数据
        /// </summary>
        private void InitTree()
        {
            treeView1.Nodes.Clear();
            treeView1.BeginUpdate();
            Cursor.Current = Cursors.WaitCursor;

            //先获取系统类型,然后对不同的系统类型下的菜单进行绑定显示
            List<SystemTypeInfo> typeList = BLLFactory<SystemType>.Instance.GetAll();
            foreach (SystemTypeInfo typeInfo in typeList)
            {
                TreeNode pNode = new TreeNode();
                pNode.Text = typeInfo.Name;//系统类型节点
                pNode.Name = typeInfo.OID;
                pNode.ImageIndex = 0;
                pNode.SelectedImageIndex = 0;
                this.treeView1.Nodes.Add(pNode);

                string systemType = typeInfo.OID;//系统标识ID

                //绑定树控件
                //一般情况下,对Ribbon样式而言,一级菜单表示RibbonPage;二级菜单表示PageGroup;三级菜单才是BarButtonItem最终的菜单项。
                List<MenuNodeInfo> menuList = BLLFactory<SysMenu>.Instance.GetTree(systemType);
                foreach (MenuNodeInfo info in menuList)
                {
                    TreeNode item = new TreeNode();
                    item.Name = info.ID;
                    item.Text = info.Name;//一级菜单节点
                    item.Tag = info;//对菜单而言,记录其MenuNodeInfo到Tag中,作为判断依据
                    item.ImageIndex = 1;
                    item.SelectedImageIndex = 1;
                    pNode.Nodes.Add(item);

                    AddChildNode(info.Children, item);
                }
            }

            Cursor.Current = Cursors.Default;
            treeView1.EndUpdate();
            this.treeView1.ExpandAll();
        }

        private void AddChildNode(List<MenuNodeInfo> list, TreeNode fnode)
        {
            foreach (MenuNodeInfo info in list)
            {
                TreeNode item = new TreeNode();
                item.Name = info.ID;
                item.Text = info.Name;//二、三级菜单节点
                item.Tag = info;//对菜单而言,记录其MenuNodeInfo到Tag中,作为判断依据
                int index = (fnode.ImageIndex + 1 > 3) ? 3 : fnode.ImageIndex + 1;
                item.ImageIndex = index;
                item.SelectedImageIndex = index;
                fnode.Nodes.Add(item);

                AddChildNode(info.Children, item);
            }
        }

菜单的列表数据,通过分页控件绑定的代码如下所示。

        /// <summary>
        /// 根据查询条件构造查询语句
        /// </summary>
        private string GetConditionSql()
        {
            SearchCondition condition = new SearchCondition();
            condition.AddCondition("Name", this.txtName.Text, SqlOperator.Like);
            condition.AddCondition("FunctionId", this.txtFunctionId.Text, SqlOperator.Like);
            condition.AddCondition("Visible", this.txtVisible.Checked ? 1 : 0, SqlOperator.Equal);
            condition.AddCondition("WinformType", this.txtWinformType.Text, SqlOperator.Like);
            condition.AddCondition("Url", this.txtUrl.Text, SqlOperator.Like);

            string where = condition.BuildConditionSql().Replace("Where", "");

            return where;
        }

        /// <summary>
        /// 绑定列表数据
        /// </summary>
        private void BindData()
        {
            //entity
            this.winGridViewPager1.DisplayColumns = "Name,Icon,Seq,FunctionId,Visible,WinformType,Url";
            #region 添加别名解析

            this.winGridViewPager1.AddColumnAlias("ID", "");
            this.winGridViewPager1.AddColumnAlias("Name", "显示名称");
            this.winGridViewPager1.AddColumnAlias("Icon", "图标");
            this.winGridViewPager1.AddColumnAlias("Seq", "排序");
            this.winGridViewPager1.AddColumnAlias("FunctionId", "功能ID");
            this.winGridViewPager1.AddColumnAlias("Visible", "菜单可见");
            this.winGridViewPager1.AddColumnAlias("WinformType", "Winform窗体类型");
            this.winGridViewPager1.AddColumnAlias("Url", "Web界面Url地址");

            #endregion

            string where = GetConditionSql();
            List<MenuInfo> list = BLLFactory<SysMenu>.Instance.FindWithPager(where, this.winGridViewPager1.PagerInfo);
            list = CollectionHelper<MenuInfo>.Fill("-1", 0, list, "PID", "ID", "Name");
            this.winGridViewPager1.DataSource = new WHC.Pager.WinControl.SortableBindingList<MenuInfo>(list);
            this.winGridViewPager1.PrintTitle = "功能菜单信息报表";
        }

菜单的编辑界面如下所示。

本篇主要是介绍菜单的管理,对于菜单的动态加载管理,我会在另外一篇Winform开发框架中进行介绍。菜单定义数据里面的功能控件ID,是来自功能模块的功能控件ID,是用来控制不同用户所能访问的菜单资源的。

3、功能管理

功能定义,也是基于某个系统类型下面的,对于不同的业务系统,我们可以集中放在一个权限管理系统里面进行管理,但是功能的定义,根据不同的系统类型进行区分即可,这样的目标是用来实现多种企业应用的有效整合。

功能的管理,是整个权限系统的核心,因为通过对他们的定义,以及权限分配,都会影响各个角色用户可访问的功能;功能定义的数据,其实也是一个树形结构,可以用树控件进行展示出来,如下所示。

4、日志管理

我们知道,一般权限系统,管理用户很常见的,因此用户的登陆日志,一般情况下是由权限管理系统记录即可, 如每次用户登陆的时候,我们记录用户的登陆日志;如果用户修改密码,我们也做一个重要记录,这样对于在业务系统端的管理,我们就不需要管理他们的登陆方面的事件了。

日志管理分为两个部分,一个是通过权限管理系统本身的登录入口进行登录的,一个是通过与之集成的业务系统,通过API调用方式进行登录验证的, 他们的登录接口基本一样,只是部分数据不同。

            try
            {
                //判断用户是否登录成功
                string ip = NetworkUtil.GetLocalIP();
                string macAddr = HardwareInfoHelper.GetMacAddress();

                string identity = BLLFactory<User>.Instance.VerifyUser(this.txtLogin.Text, this.txtPassword.Text, "WareMis", ip, macAddr);
                if (!string.IsNullOrEmpty(identity))
                {
                    //进一步判断用户角色
                    if (BLLFactory<User>.Instance.UserInRole(this.txtLogin.Text, RoleInfo.AdminName))
                    {
                        MessageUtil.ShowTips(string.Format("用户【{0}】身份验证正确", this.txtLogin.Text));
                    }
                    else
                    {
                        MessageUtil.ShowWarning("该用户没有管理员权限");
                        return;
                    }
                }
                else
                {
                    MessageUtil.ShowWarning("用户名或密码错误");
                    return;
                }
            }
            catch (Exception err)
            {
                MessageUtil.ShowError(err.Message);
            }

权限管理系统对日志进行统一管理和展示,具体界面如下所示。

整个权限管理系统,目的提高系统开发速度和效率,因此通过独立开发,模块重用,易于集成等方式实现我们生产效率的最大化。

本文转自博客园伍华聪的博客,原文链接:Winform开发框架之权限管理系统的改进,如需转载请自行联系原博主。

时间: 2024-10-25 05:28:22

Winform开发框架之权限管理系统的改进的相关文章

Winform开发框架之权限管理系统改进的经验总结(1)TreeListLoo

最近一直在做一些技术性的研究和框架改进工作,博客也落下好几天没有更新了,也该是时候静下心 来,总结这段时间的一些技术改进的经验了.和上一阶段的CRM系统开发和技术研究一样,我都喜欢在一 个项目或者模块完成后,做一些相关的总结性工作,记录下前一阶段的技术脚印,希望给自己留下一个 脚印快照,同时给读者了解自己的技术动向外,也有所收获.本随笔主要介绍在下拉列表中展示一个列 表,以便实现数据结构的良好展示,并能快速选定所需的节点,这个就是TreeListLookupEdit控件的使 用. 1.界面效果展

Winform开发框架之权限管理系统改进的经验总结(1)-TreeListLookupEdit控件的使用

最近一直在做一些技术性的研究和框架改进工作,博客也落下好几天没有更新了,也该是时候静下心来,总结这段时间的一些技术改进的经验了.和上一阶段的CRM系统开发和技术研究一样,我都喜欢在一个项目或者模块完成后,做一些相关的总结性工作,记录下前一阶段的技术脚印,希望给自己留下一个脚印快照,同时给读者了解自己的技术动向外,也有所收获.本随笔主要介绍在下拉列表中展示一个列表,以便实现数据结构的良好展示,并能快速选定所需的节点,这个就是TreeListLookupEdit控件的使用. 1.界面效果展示 首先我

Winform开发框架之权限管理系统改进经验总结(2)用户选择界面的设计

在上篇总结随笔<Winform开发框架之权限管理系统改进的经验总结(1)-TreeListLookupEdit控件 的使用>介绍了权限管理模块的用户管理部分,其中主要介绍了其中的用户所属公司.所属部门.直属 经理(人员列表)的几级数据级联的展示,通过引入TreeListLookupEdit控件,能增强用户的体验效果 .本篇继续介绍权限系统模块中的一些闪光点,介绍组织机构管理里面选择用户的界面设计和实现,用 户选择在很多场合会用到,如组织机构的用户选择,角色里面的用户选择,或者流程里面的用户选择

Winform开发框架之权限管理系统改进的经验总结(4)-一行代码实现表操作日志记录

在前面介绍了几篇关于我的权限系统改进的一些经验总结,本篇继续这一系列主体,介绍如何一行代码实现重要表的操作日志记录.我们知道,在很多业务系统里面,数据是很敏感的,特别对于一些增加.修改.删除等关键的操作,如果能在框架层面的支持基础上,以最少的代码实现重要表的日志记录,那么是一件非常值得庆贺的事情,也能够为我们客户的数据提供重要的日志跟踪,甚至是数据恢复的参考. 1.数据访问层的对象继承关系 首先,为了减少重复代码的编写,合理的继承关系是必要的,我们需要在数据访问层上建立合理的继承关系,如下是我的

Winform开发框架之权限管理系统改进的经验总结(4)--用户分级管理

在实际的系统应用环境中,用户的分级管理一般也是比较常见的功能,小的业务系统可以不需要,但是一般涉及到集团.分子公司.或者是事业单位里面的各个处室或者某某局的人员管理,这些分级管理就显得比较必要,否则单靠管理员来处理账号的事情,是比较麻烦一点的.分级管理就是让不同层次.不同机构的人员实现一定的自治管理,如分公司的人员有专门的管理员,各地区的处室或者某某局实现内部人员的创建.调整.角色分配等工作.本篇随笔主要介绍在我的权限系统中如何实现人员的分级管理的,给大家提供相应的思路和样例参考. 1.用户分级

Winform开发框架之权限管理系统改进的经验总结(2)-用户选择界面的设计

在上篇总结随笔<Winform开发框架之权限管理系统改进的经验总结(1)-TreeListLookupEdit控件的使用>介绍了权限管理模块的用户管理部分,其中主要介绍了其中的用户所属公司.所属部门.直属经理(人员列表)的几级数据级联的展示,通过引入TreeListLookupEdit控件,能增强用户的体验效果.本篇继续介绍权限系统模块中的一些闪光点,介绍组织机构管理里面选择用户的界面设计和实现,用户选择在很多场合会用到,如组织机构的用户选择,角色里面的用户选择,或者流程里面的用户选择等用途.

Winform开发框架之权限管理系统改进的经验总结(3)-系统登录黑白名单的实现

在一般的权限系统里面,可能经常会看到系统的黑名单或者白名单的拦截功能.在一般权限系统里面,常见的黑名单就是禁止用户在某些IP上登录系统,白名单就是允许用户只在某些IP上登录系统.本随笔主要介绍在我的权限系统里面,如何实现这个黑白名单的功能,以及介绍在其中应用到的IP对比操作,IP段判断等操作代码. 1.黑白名单的配置 要完成黑名单的拦截和白名单的放行,我们需要进行名单的配置操作,我们把相关的配置放到列表里面进行展示,可以添加多个黑名单或者白名单,如下界面所示. 可以单击新建按钮进行添加一条记录,

Winform开发框架之权限管理系统改进经验总结(3)系统登录黑白名单的实现

在一般的权限系统里面,可能经常会看到系统的黑名单或者白名单的拦截功能.在一般权限系统里面 ,常见的黑名单就是禁止用户在某些IP上登录系统,白名单就是允许用户只在某些IP上登录系统.本随 笔主要介绍在我的权限系统里面,如何实现这个黑白名单的功能,以及介绍在其中应用到的IP对比操作 ,IP段判断等操作代码. 1.黑白名单的配置 要完成黑名单的拦截和白名单的放行,我们需要进行名单的配置操作,我们把相关的配置放到列表里 面进行展示,可以添加多个黑名单或者白名单,如下界面所示. 开发框架之权限管理系统改进

Winform开发框架之权限管理系统改进的经验总结(5) 用户分级管理

在实际的系统应用环境中,用户的分级管理一般也是比较常见的功能,小的业务系统可以不需要,但 是一般涉及到集团.分子公司.或者是事业单位里面的各个处室或者某某局的人员管理,这些分级管理 就显得比较必要,否则单靠管理员来处理账号的事情,是比较麻烦一点的.分级管理就是让不同层次. 不同机构的人员实现一定的自治管理,如分公司的人员有专门的管理员,各地区的处室或者某某局实现 内部人员的创建.调整.角色分配等工作.本篇随笔主要介绍在我的权限系统中如何实现人员的分级管 理的,给大家提供相应的思路和样例参考. 1