【Aspx应用开发平台教程】架构篇:解析微系统构件-数据权限的实现

  在园中,讲数据权限的文章很多,但大部分文章都是浅尝即止,只讲到数据库设计就没了,往往最关键的部分,如何在项目中实现,讲得很少。今天,我就详细介绍一下在 Aspx应用开发平台 中数据权限的实现方式。

 

  在 Aspx应用开发平台 中,数据权限有四种实现方式:

  • 页面权限;
  • 模块权限;
  • 数据访问权限;
  • 表单权限;

1. 页面权限

  在 Aspx应用开发平台 中,页面通过【菜单对象】来进行管理,用户通过点击菜单来访问页面,因此,我们在【菜单】编辑时指定相应的用户角色即可实现权限控制。

  当 用户直接输入页面Url访问时,系统可以通过检查Url找到对应的菜单,进而检查授权角色是否合法。

  

2. 模块权限

  我们通常会将一组功能相近的功能页面。组成一个【功能模块】,分配给相应的用户使用,在 Aspx应用开发平台 中,这个功能是通过【导航栏目设置】完成的。一般情况下,要求分配用户的粒度更为细腻,比如要求直接分配给某个用户、某个部门、某个职务等等,为此,在 【导航栏目设置】中,我们采用 【用户选择控件】来绑定用户。

  

  打开 【选择用户】页面,我们可以按 用户组、角色、部门、职务等等选择,也可以直接选定用户。

 

3.数据访问权限

  在项目开发中,经常会有这样的需求:

  • 角色A是系统管理员,可以查看修改所有的数据,
  • 角色B是普通用户。只能查看修改自己的数据;
  • 角色C是部门领导,可以查看修改本部门所有用户的数据;
  • 未提交的订单可以修改,已经提交的订单不能修改;
  • 新提交的数据,在三天内可以修改,超过三天后锁定;
  • 。。。

  不难发现,很多数据权限的要求都是相同的,为此,我们参考Window的安全策略模式,定义了【数据策略】这一权限控制模型。在 Aspx应用开发平台 中,微系统控件是通过 绑定 用户角色数据策略 的对应关系,实现数据访问权限控制。

 

 

  那么【数据策略】又是怎样组成的呢?

 

  【数据策略】由 【数据筛选条件】对象和相应的界面操作定义组成,由 【数据筛选条件】给出数据的筛选条件,比对数据是否符合筛选条件,符合条件的数据用定义的操作界面进行操作。【数据筛选条件】是实现 【筛选器】接口的对象。

 

 

ExpandedBlockStart.gif 筛选器接口
namespace ObjectService.Filter
{
    using System;
    using System.Data;
    
    /// 
< summary >
    /// 筛选器接口
    /// 
< example >
    ///  
< code  source ="..\ObjectService\Filter\IFilter.cs"  lang ="c#"   ></ code >
    /// 
</ example >
    /// 
</ summary >
    public interface IFilter
    {
        /// 
< summary >
        /// 获得数据筛选条件
        /// 
</ summary >
        /// 
< param  name ="dataEntityName" > 数据实体名称 </ param >
        /// 
< returns > 数据筛选条件 </ returns >
        string GetRecordFilter(string dataEntityName);
      
        /// 
< summary >
        /// 判断记录是否符合数据筛选条件
        /// 
</ summary >
        /// 
< param  name ="dataEntityName" > 数据实体名称 </ param >
        /// 
< param  name ="key" > 主键 </ param >
        /// 
< returns > 符合数据筛选条件标志 </ returns >
        bool InFilter(string dataEntityName, object key);

        /// 
< summary >
        /// 判断记录是否符合数据筛选条件
        /// 
</ summary >
        /// 
< param  name ="row" > 数据列 </ param >
        /// 
< returns > 符合数据筛选条件标志 </ returns >
        bool InFilter(DataRow row);


        /// 
< summary >
        /// 判断当前用户是否符合数据筛选条件
        /// 
</ summary >
        /// 
< param  name ="row" > 数据列 </ param >
        /// 
< param  name ="userId" > 用户编号 </ param >
        /// 
< returns > 符合数据筛选条件标志 </ returns >
        bool InFilter(DataRow row,string userId);

    }
     
}

 

  

   【部门数据筛选器】的实现代码:

 

ExpandedBlockStart.gif 部门数据筛选器
namespace AspxWork.OAHelper.HR
{
    using ObjectService;
    using System;
    using System.Data;
    using UserHelper;
    using ObjectService.Filter;

    /// 
< summary >
    /// 部门数据筛选对象
    /// 
</ summary >
    public class DepartmentFilter : IFilter
    {
        /// 
< summary >
        /// 获得数据筛选条件
        /// 
</ summary >
        /// 
< param  name ="dataEntityName" > 数据实体名称 </ param >
        /// 
< returns > 数据筛选条件 </ returns >
        public string GetRecordFilter(string dataEntityName)
        {
            string departmentId = WebControlLibrary.Globals.User.DepartmentId;

            ObjectService.IDataEntityProvider dataEntity = ObjectService.Factory.CreateDataEntity(dataEntityName);

            return dataEntity.Table.Columns["DepartmentId"] != null ? DepartmentHandler.Current.GetFilter("DepartmentId", departmentId) : String.Format(" UserId in ( Select UserId from t_Users where {0} )", DepartmentHandler.Current.GetFilter("Department", departmentId));
        }

        /// 
< summary >
        /// 判断记录是否符合数据筛选条件
        /// 
</ summary >
        /// 
< param  name ="dataEntityName" > 数据实体名称 </ param >
        /// 
< param  name ="key" > 主键 </ param >
        /// 
< returns > 符合数据筛选条件标志 </ returns >
        public bool InFilter(string dataEntityName, object key)
        {
            ObjectService.IDataEntityProvider dataEntity = ObjectService.Factory.CreateDataEntity(dataEntityName);

            DataRow row = dataEntity.Edit(key);

            string departmentId = WebControlLibrary.Globals.User.DepartmentId;

            return dataEntity.Table.Columns["UserId"] != null ? DepartmentHandler.Current.IsInDepartment(row["UserId"].ToString(),departmentId) : false;
        }

        /// 
< summary >
        /// 判断记录是否符合数据筛选条件
        /// 
</ summary >
        /// 
< param  name ="row" > 数据列 </ param >
        /// 
< returns > 符合数据筛选条件标志 </ returns >
        public bool InFilter(DataRow row)
        {
            string departmentId = WebControlLibrary.Globals.User.DepartmentId;

            return row.Table.Columns["UserId"] != null ? DepartmentHandler.Current.IsInDepartment(row["UserId"].ToString(), departmentId) : false;
     
        }


        /// 
< summary >
        /// 判断当前用户是否符合数据筛选条件
        /// 
</ summary >
        /// 
< param  name ="row" > 数据列 </ param >
        /// 
< param  name ="userId" > 用户编号 </ param >
        /// 
< returns > 符合数据筛选条件标志 </ returns >
        public bool InFilter(DataRow row, string userId)
        {
            string departmentId = UserHelper.UserHandler.Current[userId].DepartmentId;

            return row.Table.Columns["UserId"] != null ? DepartmentHandler.Current.IsInDepartment(row["UserId"].ToString(), departmentId) : false;
        }
    }
}

 

 

  【数据策略】又是怎样和 【微系统构件】结合在一起运作呢?如果你仔细看过前面文章中,【微系统构件】的程序代码,你就会发现,每个读取数据的方法都是这样的:

 

ExpandedBlockStart.gif 获得数据筛选条件代码
        ///  < summary >
        /// 获得符合数据筛选条件的DataView对象,并排序
        /// 
</ summary >
        /// 
< param  name ="recordFilter" > 数据筛选条件 </ param >
        /// 
< param  name ="order" > 排序条件 </ param >
        /// 
< returns > DataView对象 </ returns >
        public virtual DataView GetDataView(string recordFilter, string order)
        {
            System.Data.DataSet dataSet = new System.Data.DataSet();

            DataAccess.LoadByCondition(dataSet,GetRecordFilter(recordFilter),order, ViewName);

            return new DataView(dataSet.Tables[this.ViewName]);
        }

       /// 获得对应的数据筛选条件
        /// 
</ summary >
        /// 
< param  name ="recordFilter" > 数据筛选条件 </ param >
        /// 
< returns > 数据筛选条件 </ returns >
        protected virtual string GetRecordFilter( string recordFilter)
        {
            return ObjectService.Factory.GetRecordFilter(TableName, recordFilter);
        }

 

 

   对象工厂从微系统构件绑定的数据策略和用户角色中,读出对应的数据筛选条件,插入现有的数据筛选条件,达到数据访问控制的目的。

 

  此外,在数据列表页面,我们通过在数据列表控件的列生成事件中,创建数据访问权限对象,根据数据策略,获得数据访问权限,控制列的生成,实现控制数据列的权限。

 

ExpandedBlockStart.gif 数据列权限
void Grid_ItemContentCreated(object sender, GridItemContentCreatedEventArgs e)
        {
            DataRow row = (DataRow)e.Item.DataItem;

            string html = String.Empty;
            
            
            AspxWork.FormHelper.Popedom.Popedom currentPopedom;

            //获得当前操作权限对象
            if (isSetPopedom)
            {
                currentPopedom = popedom;
            }
            else
            {
                if (popedomEntity != null)
                    currentPopedom = new AspxWork.FormHelper.Popedom.Popedom(popedomEntity, WebControlLibrary.Globals.User.UserId, row);
                else
                    currentPopedom = new AspxWork.FormHelper.Popedom.Popedom(tableName, WebControlLibrary.Globals.User.UserId, row);
            }

            bool isReadOnly = currentPopedom.IsReadonly;

            bool isAllowDelete = currentPopedom.IsAllowDelete;

            bool isAllowEdit = currentPopedom.IsAllowEdit;


            DataStatusEntity dataStatus = StatusHandler.Current.GetDataStatus(TableName, row);

            if (dataStatus != null)
            {
                isAllowDelete = dataStatus.IsAllowDelete && currentPopedom.IsAllowDelete;

                isAllowEdit = dataStatus.IsAllowEdit && popedom.IsAllowEdit;

                if (!dataStatus.IsAllowEdit || !currentPopedom.IsAllowEdit)
                    isReadOnly = true;
            }


            if (currentPopedom.IsAllowView)
            {
                

                string key = WebControlLibrary.Url.SetRequestUrl("
&Key =" + row[DataEntity.KeyName].ToString(), "Key");

                if (this.TableEntity.IsOtherWindow)
                {
                    if (isReadOnly)
                        html = "
< href =\""  + parameter.ReadonlyUrl + key + "\" > 查看 </ a >   | ";
                    else
                    {
                        html = "
< href =\""  + parameter.ReadonlyUrl + key + "\" > 查看 </ a >   | ";
                        html += "
< href =\""  + parameter.EditUrl + key + "\" > 编辑 </ a >   | ";
                    }
                }
                else
                {
                    if (!isReadOnly)
                        html = String.Format("
< href =\"javascript:Grid.edit(Grid.getItemFromClientId('0  {0}'));\" > ", row[DataEntity.KeyName].ToString()) + "编辑 </ a >   | ";
                }

                
            }


            if (isAllowDelete)
            {
                html += String.Format("
< href =\"javascript:GridDelete(Grid.getItemFromClientId('0  {0}'))\" > 删除 </ a > ", row[DataEntity.KeyName].ToString());
            }

            if (!String.IsNullOrEmpty(html))
                e.Content.Controls.Add(new LiteralControl(html));
        }

 

3.表单权限

  由于 Aspx应用开发平台 的表单都是通过表单设计器设计构建的,因此,对表单权限的控制就非常简单了,可以用代码直接控制:

            //设置表单为只读
            this.ControlContainer.IsReadOnly = true;

            //设置表单的第二个控件为只读
            this.ControlContainer[1].IsReadOnly = true;

   

  也可以通过设计器设置控制,比如 在工作流设置中,设置表单权限:

 

 

  感兴趣的同仁,可以到我们的网站 http://www.doasp.cn/ 下载学习版,有完整的实现源代码。

 

转载于:https://www.cnblogs.com/ynfengjun/archive/2010/10/18/1853961.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值