如何在应用系统中实现数据权限的控制功能(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();
                    }

以上就是我对数据权限控制的一些心得和实现思路,希望大家能够体会其中的思路,并批判性的提出意见和建议。

时间: 2024-10-23 08:00:14

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

系统中做数据权限的方法

在系统开发中,我们为了保证,不同级别员工的账号,登录系统时,查询到这个员工应该看到的数据,而不属于他级别范围内的数据,不应该看到,比如普通员工只能看到他所在中心的数据,而经理则能看到多个中心的数据,这怎么实现呢,这就是今天我们所讲的数据权限了! 其实很简单,我们只需要一张表管理就够了,就叫员工机构表好了,一个字段为员工编号,另一个字段为机构了,机构的数据用逗号隔开存在一个字段里面 那么后台如何去用这个数据呢 1.根据员工编码去查询机构编码 2.将机构编码放到集合中 3.将这个集合放到查询条件中

实现业务系统中的用户权限管理--设计篇

B/S系统中的权限比C/S中的更显的重要,C/S系统由于具有特殊的client,所以訪问用户的权限检測能够通过client实现或通过client+server检測实现,而B/S中,浏览器是每一台计算机都已具备的,假设不建立一个完整的权限检測,那么一个"非法用户"非常可能就能通过浏览器轻易訪问到B/S系统中的全部功能.因此B/S业务系统都须要有一个或多个权限系统来实现訪问权限检測,让经过授权的用户能够正常合法的使用已授权功能,而对那些未经授权的"非法用户"将会将他们彻

[转]实现业务系统中的用户权限管理--设计篇

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

实现业务系统中的用户权限管理--实现篇

在设计篇中,我们已经为大家阐述了有关权限管理系统的数据库设计,在本篇中,我们将重点放在其实现代码部分.为了让你能够更直接更有效的看到全部动作的代码,我们使用"动作分解列表"的方式来陈述每个动作以及相关资源. 实现权限管理功能的动作 动作分解 动作名 相关表名 操作集类型 (S,U,I,D,SQL) 表单 模组 字符资源 是否分页? 返回提示? 权限检测 权限初始化安装 setup 无 无 无 setup setupok 否 否 否 显示添加管理组界面 addnewgroup 无 无 a

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

在Finder中定位到要修改权限的文件或应用 通过“文件”菜单栏或右键菜单选择“显示简介”(快捷键Cmd+I) 找到简介面板的最下方的“共享与权限”(Sharing&Permissions)部分 按需对不同用户赋予权限:读与写(readandwrite).只读(readonly).无访问权限(no access) 权限设置完成后关闭文件简介面板后立即生效.同时,您也可以配合之前介绍的“OSX系统内置FTP工具”技巧使用. 当然,你也可以利用命令行模式来对文件权限进行修改;本文就不涉及了,大家可以

对liunx系统中用户和权限管理一点小心得

近期才接触Liunx,给我的感觉,并不是很难,但是知识点很多,命令杂,并且附带了茫茫多的选项.接下来我就拿用户和权限管理来举个例子. 一丶用户&组的创建,管理. 用户,顾名思义,就是在系统上的接口进行操作的人. 用户分为:1.管理员(root)2.普通用户(user):系统用户和登录用户 管理员比较好理解,好比说一个国家的国王,拥有对国家最高的指挥权.root在linux系统中就扮演了国王的角色,任何的权限对它来说都形同虚设. 而普通用户,相当于这个国家的公民,必须遵循国家规定的法律. 普通用户

linux系统中文件的权限

查看文件权限的语句: 在终端输入:ls -l xxx.xxx (xxx.xxx是文件名) 那么就会出现相类似的信息,主要都是这些:-rw-rw-r-- 一共有10位数 其中: 最前面那个 - 代表的是类型 中间那三个 rw- 代表的是所有者(user) 然后那三个 rw- 代表的是组群(group) 最后那三个 r-- 代表的是其他人(other) 然后我再解释一下后面那9位数: r 表示文件可以被读(read) w 表示文件可以被写(write) x 表示文件可以被执行(如果它是程序的话) -

Linux系统中的相关权限

文件权限 1.文件属性的查看 ls -l filename-|rw-r--r--.|1| root| root|   46|Oct  1 05:03 |filename- ---------  -  ---- ----    --  ------------ -------- 1    2       3   4      5      6     7             8 1."-":文件类型 -    普通文件d    目录c    字符设备s    套接字p    管道b 

debian系统中添加sudo权限

刚安装好的Debian默认还没有sudo功能.1.安装sudo# apt-get install sudo2.修改 /etc/sudoers 文件属性为可写# chmod +w /etc/sudoers3.编辑 /etc/sudoers ,添加如下行# vim /etc/sudoersroot ALL=(ALL) ALLuser ALL=(ALL) ALL   #用户user执行sudo时需要密码.user为自己的系统登陆名称#user ALL=NOPASSWD:ALL  #用户user执行su