如何在应用系统中实现数据权限的控制功能(2)

关于数据权限的控制,可能我们在做很多大型一点的系统都会碰到过,可能每个人设计和解决问题的思路都有所不同,本文介绍我自己框架里面的解决思路。从上一篇《如何在应用系统中实现数据权限的控制功能》里面我们可能对权限控制和数据权限的控制有了一个初步的了解,本文接着进一步介绍在应用系统中,如何集成数据权限的控制功能。

1、数据权限实现思路分析

为了实现数据权限的控制,我们需要在通用的权限系统里面保存好对应角色具有哪些组织机构的数据权限,然后在应用系统中调用API进行过滤数据处理即可。

为了实现以上的功能需求,我们需要在权限系统里面,角色控制哪里增加一个数据权限的数据存储。

实际的应用系统,当用户登陆成功后,我们获取并记录好其可以管理的公司或者部门,如果是主管的角色,可能有多个公司的数据可以管理,那么可以在程序的顶部,让用户选择管理那个公司的数据即可,如果切换公司,那么刷新现有的界面数据显示就可以了。

在用户成功登陆后,我们可以记录用户的相关权限控制信息,如他所能控制数据的公司或者部门,把它记录下来。

                        Portal.gc.CompanyList = BLLFactory<RoleData>.Instance.GetBelongCompanysByUser(info.ID);
                        List<int> deptList = BLLFactory<RoleData>.Instance.GetBelongDeptsByUser(info.ID);
                        Portal.gc.DeptList = deptList;

然后存储用户默认的公司ID,并根据用户是否为管理员(超级管理员、公司管理员),然后构造一个通用的过滤条件,放到全局缓存里面,方便各个模块使用,如下代码所示。

                        //设置选定的公司ID(默认为用户所在公司的ID)
                        Cache.Instance["SelectedCompanyID"] = info.Company_ID;
                        //设置过滤条件给界面基类使用
                        string filterCondition = string.Format(" Company_ID = '{0}' ", info.Company_ID);
                        if (!Portal.gc.IsAdmin)
                        {
                            if (deptList.Count > 0)
                            {
                                filterCondition += string.Format(" AND Dept_ID IN ({0})", string.Join(",", deptList));
                            }
                            else
                            {
                                filterCondition += string.Format(" AND Creator = '{0}' ", info.ID);
                            }
                        }
                        Cache.Instance["DataFilterCondition"] = filterCondition;

在主界面的时候,我们可以根据用户所能管理的公司数据,在顶部初始化公司列表,方便切换选择,以下是初始化的代码。

            //添加受管理的公司机构
            //判断如果用户管理的公司数据多于一个,那么就显示选择单位列表,并绑定公司数据
            if (Portal.gc.CompanyList.Count > 1)
            {
                this.repositoryCompanyItem.Items.Clear();
                foreach (int company in Portal.gc.CompanyList)
                {
                    OUInfo companyInfo = BLLFactory<OU>.Instance.FindByID(company);
                    if (companyInfo != null)
                    {
                        this.repositoryCompanyItem.Items.Add(new CListItem(companyInfo.Name, companyInfo.ID.ToString()));
                    }
                }

                //多于一个显示公司下拉列表
                this.barCompanyItem.Visibility = DevExpress.XtraBars.BarItemVisibility.Always;
            }
            else
            {
                //只有一个公司时候,屏蔽公司选择列表
                this.barCompanyItem.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
            }

如果多于一个公司,那么正常的需求是可以切换公司来查看其它公司的数据的,要实现这个功能,那么就需要修改登陆的那个全局的过滤条件:Cache.Instance["DataFilterCondition"]了。

我们来看看代码的实现,其主要的逻辑就是获取用户选择的公司ID,然后根据公司、部门信息,重新构建一个全局的过滤条件,并重新缓存到对应的键值里面去,供后面的窗体实现数据的过滤更新。

                CListItem item = this.barCompanyItem.EditValue as CListItem;
                if (item != null)
                {
                    //设置选定的公司ID
                    Cache.Instance["SelectedCompanyID"] = item.Value;
                    SetSelectedCompanyName();

                    //设置过滤条件给界面基类使用
                    string filterCondition = string.Format(" Company_ID = '{0}' ", item.Value);
                    if (!Portal.gc.IsAdmin)
                    {
                        if (Portal.gc.DeptList.Count > 0)
                        {
                            filterCondition += string.Format(" AND Dept_ID IN ({0})", string.Join(",", Portal.gc.DeptList));
                        }
                        else
                        {
                            filterCondition += string.Format(" AND Creator = '{0}' ", Portal.gc.UserInfo.ID);
                        }
                    }
                    Cache.Instance["DataFilterCondition"] = filterCondition;

如果需要对已有的窗体实现数据更新,那么遍历窗体,并统一实现数据刷新即可。

                    //遍历全部窗口,更新
                    foreach (WHC.Framework.BaseUI.BaseDock form in this.MdiChildren)
                    {
                        form.SelectedCompanyID = item.Value;
                        form.DataFilterCondition = filterCondition;
                        form.FormOnLoad();
                    }

                    string message = string.Format("您已经切换数据显示:{0}", item.Text);
                    MessageDxUtil.ShowTips(message);

 2、窗体数据过滤的实现

从上面的步骤代码,我们可以看到如何构建一个全局的过滤条件,但是我们获取数据的时候,如何才能实现数据权限的控制,让用户所能看到的数据在可控的范围内呢?

我们知道,一般窗体数据列表的绑定操作类似如下代码所示

        /// <summary>
        /// 绑定列表数据
        /// </summary>
        private void BindData()
        {
            //entity
            this.winGridViewPager1.DisplayColumns = displayColumns;
            this.winGridViewPager1.ColumnNameAlias = CallerFactory<ICustomerService>.Instance.GetColumnNameAlias();//字段列显示名称转义

            string where = GetConditionSql();
            PagerInfo pagerInfo = this.winGridViewPager1.PagerInfo;
            List<CustomerInfo> list = CallerFactory<ICustomerService>.Instance.FindWithPager(where, ref pagerInfo);
            this.winGridViewPager1.DataSource = new WHC.Pager.WinControl.SortableBindingList<CustomerInfo>(list);
            this.winGridViewPager1.PrintTitle = "客户信息列表";
        }

所以主要的数据控制,就在函数GetConditionSql()里面了,那么这个里面,我们如何整合前面的过滤条件呢?

下面是一个案例代码。

        /// <summary>
        /// 根据查询条件构造查询语句
        /// </summary>
        private string GetConditionSql()
        {
            //如果存在高级查询对象信息,则使用高级查询条件,否则使用主表条件查询
            SearchCondition condition = advanceCondition;
            if (condition == null)
            {
                condition = new SearchCondition();
                if(customGridLookUpEdit1.EditValue != null)
                {
                    condition.AddCondition("ID", customGridLookUpEdit1.EditValue.ToString(), SqlOperator.Equal);
                }
                condition.AddCondition("Deleted", 0, SqlOperator.Equal);//不显示删除的
            }
            string where = condition.BuildConditionSql().Replace("Where", "");

            //如果是单击节点得到的条件,则使用树列表的,否则使用查询条件的
            if (!string.IsNullOrEmpty(treeConditionSql))
            {
                where = treeConditionSql + " AND Deleted = 0 ";//不显示删除的
            }

            //数据权限的过滤:过滤规则,如果指定公司,以公司过滤,如果进一步指定部门,以公司+部门进行过滤;否则以个人的数据展示
            //如果过滤条件不为空,那么需要进行过滤
            if (!string.IsNullOrEmpty(this.DataFilterCondition))
            {
                where += string.Format(" AND {0}", this.DataFilterCondition);
            }
            return where;
        }

我们主要关注下上面红色部分即可,因为我们已经加上了标准的过滤条件了,这样我们就可以看到自己管理的数据了。

为了实现统一的数据控制,我们要求整个业务表的设计,需要引入下面几个标准的字段,这样就能很好使用过滤条件进行数据的过滤了。

前面也介绍到了,窗体可以统一刷新,其奥秘就是它们遵循统一的一个数据加载接口,我们初始化窗体数据的函数代码如下所示。

        /// <summary>
        /// 编写初始化窗体的实现,可以用于刷新
        /// </summary>
        public override void FormOnLoad()
        {
            InitDictItem();

            BindData();
            InitCustomerPage();
        }

所以它们就能够统一调用FormOnLoad来统一刷新数据,就是这个道理。

                    //遍历全部窗口,更新
                    foreach (WHC.Framework.BaseUI.BaseDock form in this.MdiChildren)
                    {
                        form.SelectedCompanyID = item.Value;
                        form.DataFilterCondition = filterCondition;
                        form.FormOnLoad();
                    }

本文转自博客园伍华聪的博客,原文链接:如何在应用系统中实现数据权限的控制功能(2),如需转载请自行联系原博主。

 

时间: 2024-09-18 21:30:20

如何在应用系统中实现数据权限的控制功能(2)的相关文章

如何在应用系统中实现数据权限的控制功能

在很多应用行业里面,都对数据的权限做了特别的声明,如对于销售,财务的数据,它们是非常敏感的,因此要求对数据权限进行控制,对于基于集团性的应用系统而言,就更多需要控制好各自公司的数据了.如默认只能看本公司.或者本部门的数据,对于特殊的领导,可能需要跨部门的数据,因此不能硬编码那个领导该访问哪些数据,需要进行后台的权限和数据权限的控制为佳,本文主要针对这个特点,对这个数据权限的功能模块进行探讨,并以我的Winform开发框架的实际案例进行剖析,介绍实际项目中对数据权限的控制管理. 1.权限系统的控制

在应用系统中实现数据权限的控制功能

在很多应用行业里面,都对数据的权限做了特别的声明,如对于销售,财务的数据,它们是非常敏感的,因此要求对数据权限进行控制,对于基于集团性的应用系统而言,就更多需要控制好各自公司的数据了.如默认只能看本公司.或者本部门的数据,对于特殊的领导,可能需要跨部门的数据,因此不能硬编码那个领导该访问哪些数据,需要进行后台的权限和数据权限的控制为佳,本文主要针对这个特点,对这个数据权限的功能模块进行探讨,并以我的Winform开发框架的实际案例进行剖析,介绍实际项目中对数据权限的控制管理. 1.权限系统的控制

复杂系统中的用户权限数据库设计解决方案_数据库其它

B/S系统中的权限比C/S中的更显的重要,C/S系统因为具有特殊的客户端,所以访问用户的权限检测可以通过客户端实现或通过客户端+服务器检测实现,而B/S中,浏览器是每一台计算机都已具备的,如果不建立一个完整的权限检测,那么一个"非法用户"很可能就能通过浏览器轻易访问到B/S系统中的所有功能.因此B/S业务系统都需要有一个或多个权限系统来实现访问权限检测,让经过授权的用户可以正常合法的使用已授权功能,而对那些未经授权的"非法用户"将会将他们彻底的"拒之门外&

怎么把notes开发的系统中的数据存储到sql-server中????

问题描述 怎么把notes开发的系统中的数据存储到sql-server中???? 解决方案 解决方案二:方法有很多种解决方案三:用LEI就可以解决方案四:SubClick(SourceAsButton)OnErrorGotoErrorHandleDimwsAsNewNotesUIWorkspaceDimsessionAsNewNotesSessionDimdbAsNotesDatabaseDimviewAsNotesViewDimcolumnAsNotesViewColumnDimdocAsNo

详解Linux系统中的root权限控制

  在Linux操作系统中,root的权限是最高的,也被称为超级权限的拥有者.普通用户无法执行的操作,root用户都能完成,所以也被称之为超级管理用户. 在系统中,每个文件.目录和进程,都归属于某一个用户,没有用户许可其它普通用户是无法操作的,但对root除外.root用户的特权性还表现在root 可以超越任何用户和用户组来对文件或目录进行读取.修改或删除(在系统正常的许可范围内);对可执行程序的执行.终止;对硬件设备的添加.创建和移除等; 也可以对文件和目录进行属主和权限进行修改,以适合系统管

详解Linux系统中的文件权限设置

你要明白的第一件事是文件权限可以用来干什么.当你设置一个分组的权限时发生了什么?让我们将其展开来说,这个概念就真的简单多了.那到底什么是权限?什么是分组呢? 你可以设置的3种权限: 1.读 - 允许该分组读文件(用r表示) 2.写 - 允许该分组写文件(用w表示) 3.执行 - 允许该分组执行(运行)文件(用x表示) 为了更好地解释这如何应用于一个分组,例如,你允许一个分组可以读写一个文件,但不能执行.或者,你可以允许一个分组读和执行一个文件,但不能写.甚至你可以允许一个分组有读.写.执行全部的

Linux系统中网络数据存储工具命令TcpDump的使用教程

Linux中强大的网络数据采集分析工具--TcpDump tcpdump采用命令行方式,它的命令格式为: tcpdump [ -adeflnNOpqStvx ] [ -c 数量 ] [ -F 文件名 ] [ -i 网络接口 ] [ -r 文件名] [ -s snaplen ] [ -T 类型 ] [ -w 文件名 ] [表达式 ] 1. tcpdump的选项介绍 -a    将网络地址和广播地址转变成名字: -d    将匹配信息包的代码以人们能够理解的汇编格式给出: -dd    将匹配信息包

如何在Win7系统中复制带有权限的文件

Win7系统的文件权限方面和以往的xp相比严格了许多,我们在复制普通的文件的时候并没有多大改变,但是当我们想复制一个带有权限的文件并且想保留该文件的权限设置的时候,该怎么去做呢? 第一步:打开开始菜单在搜索栏中输入"cmd".在栏目上方看到cmd程序后,用鼠标右键点击它,并在右键菜单中点寻以管理员身份运行". ▲使用管理员权限运行CMD 第二步:假设我们想把C:abc这个带有权限的文件夹复制到D:abc这个文件夹中,在弹出的命令提示符窗口中,输入"xcopy C:a

在 Mac OS X 系统中修改文件权限

  在 Finder 中定位到要修改权限的文件或应用 通过"文件"菜单栏或右键菜单选择"显示简介"(快捷键 Cmd + I) 找到简介面板的最下方的"共享与权限"(Sharing & Permissions)部分 按需对不同用户赋予权限:读与写(read and write).只读(read only).无访问权限(no access) 权限设置完成后关闭文件简介面板后立即生效.