`
feipigwang
  • 浏览: 745679 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

将权限引入系统的探索

 
阅读更多
很久以前就尝试过使用AOP进行权限控制的管理,那时候只是试试而已,并没有在项目中应用过,最近跟的一个B/S项目中要求我们把权限管理加进去,于是我考虑以前的AOP方法是否真的可行。思考许久后的结果是,可行,但是太麻烦。
主要原因在于需要在UI层<=>逻辑层<=>数据层之外增加额外的一层来使得AOP拦截可以以恰当的粒度、恰当的时机切入。如果不增加额外的这一层而使用AOP就可能会得到这样的结果--比如,在业务逻辑层或数据层使用AOP切入,就有可能出现这样的情形,用户花了老大的劲将要录入的信息敲入了,最后当点击“提交”时,系统却提示说“你没有权限进行添加操作!”。如果你是这个用户,你一定会郁闷得吐血!
所以,如果系统不允许用户添加,则根本就不应该让添加的Page或Form出现在用户眼前,然而,这在逻辑层或数据层是无法获取这个信息的,只有UI层知道这是发生在什么时刻。但是,在UI层使用AOP截获,你看见过么?我没有,我相信那不是一件容易做的工作。

于是,我开始寻找AOP之外的方法,终于,我找到了一个自己还比较满意的解决方案。下面我们以B/S系统为例,来详细描述这个方案,如果是C/S系统,可以类推之。
为了构建一个在不同B/S系统中可以复用的解决方案,我们需要规范化(定义)一些基础设施或元素。首先,我们需要定义权限的类别,比如最常见的有浏览、添加、修改、删除。你也许已经想到使用一个枚举就可以了。但是,不能使用枚举,因为枚举是sealed,不能被继承,这就意味着权限类别将不能被自定义扩展,所以,我没有使用enum,而是使用class。
///<summary>
///应用可以扩展PermissionType,以增加其它权限类别,比如审核等
///自定义类别取值应大于5
///</summary
publicclassPermissionType
{
publicconstintBrowse=1;
publicconstintAdd=2;
publicconstintUpdate=3;
publicconstintDelete=4;
}
这样,如果具体应用中有更多的权限类别,只要从PermissionType继承即可。比如,应用中需要添加“审核”、“消审”的权限,则可以
publicclassMGPPermissionType:PermissionType
{
publicconstintAudit=10;//审核
publicconstintCancelAudit=11;//消审
}
一个用户所拥有的权限可以使用IPermission接库进行规范:
///<summary>
///应用可以扩展IPermission,以增加其它权限类别,比如审核等
///</summary>
publicinterfaceIPermission
{
boolCanBrowse{get;}
boolCanAdd{get;}
boolCanUpdate{get;}
boolCanDelete{get;}
}
如果应用需要增加别的权限,也可以在实现这个接口的类中进行扩展,比如
GeneralPermission
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> #regionGeneralPermission
publicclassGeneralPermission:IPermission
{
publicboolHasNonePermit
{
get
{
return!(CanBrowse||CanAdd||CanUpdate||CanDelete||CanAudit||CanCancelAudit);
}
}

#regionIPermission成员
#regionCanBrowse
privateboolcanBrowse=false;
publicboolCanBrowse
{
get
{
returnthis.canBrowse;
}
set
{
this.canBrowse=value;
}
}
#endregion

#regionCanAdd
privateboolcanAdd=false;
publicboolCanAdd
{
get
{
returnthis.canAdd;
}
set
{
this.canAdd=value;
}
}
#endregion

#regionCanUpdate
privateboolcanUpdate=false;
publicboolCanUpdate
{
get
{
returnthis.canUpdate;
}
set
{
this.canUpdate=value;
}
}
#endregion

#regionCanDelete
privateboolcanDelete=false;
publicboolCanDelete
{
get
{
returnthis.canDelete;
}
set
{
this.canDelete=value;
}
}
#endregion

#regionCanAudit
privateboolcanAudit=false;
publicboolCanAudit
{
get
{
returnthis.canAudit;
}
set
{
this.canAudit=value;
}
}
#endregion

#regionCanCancelAudit
privateboolcanCancelAudit=false;
publicboolCanCancelAudit
{
get
{
returnthis.canCancelAudit;
}
set
{
this.canCancelAudit=value;
}
}
#endregion



#endregion
}
GeneralPermission扩展了IPermission接口,添加了“审核”、“消审”的权限。

在B/S系统中,如果用户要求做一件没有权限的事情时,通常会转到一个给出提示信息“没有相应权限”的page。但是,当用户没有权限时,到底该怎么做,我们把这个权利留给具体的应用,这里只是用接口来规范它:
publicinterfaceIPermissionHelper
{
voidOnHaveNoPermission(intpType,HttpResponseresponse);
boolVerifyCustomPermission(IPermissionper,intpType);//验证自定义的权限类型
}
OnHaveNoPermission方法就是应用在用户没有权限操作时定义要做的事情。通过上面的介绍,VerifyCustomPermission方法的作用就一幕了然了。比如下面这个IPermissionHelper实现:
PermissionHelper
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> publicclassPermissionHelper:IPermissionHelper
{
#regionIPermissionHelper成员

publicboolVerifyCustomPermission(IPermissionper,intpType)
{
GeneralPermissiongPermission
=(GeneralPermission)per;

boolb1=(pType==MGPPermissionType.Audit)&&(!gPermission.CanAudit);
boolb2=(pType==MGPPermissionType.CancelAudit)&&(!gPermission.CanCancelAudit);

if(b1||b2)
{
returnfalse;
}

returntrue;
}

publicvoidOnHaveNoPermission(intpType,HttpResponseresponse)
{
response.Redirect(
"/MGPMIS/ErrorInfoForm.aspx");
}

#endregion
}

好了,一切准备就绪,主角可以出场了,PermissionController--所有与权限相关的操作都有它来转发,如果权限满足,则调用目标操作或转到目标页面;如果条件不满足,就调用IPermissionHelper.OnHaveNoPermission方法,一切清晰明了。
PermissionController
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> ///<summary>
///用于将B/S中的权限管理集中起来。
///zhuweisky2006.04.08
///</summary>
publicclassPermissionController
{
privateIPermissionHelperpermissionHelper;

publicPermissionController(IPermissionHelperhelper)
{
this.permissionHelper=helper;
}

#regionExcute
///<summary>
///如果权限满足,则转到目标url
///</summary>
publicvoidExcute(IPermissionper,intpType,HttpResponseresponse,stringdestUrl)
{
boolb1=(pType==PermissionType.Browse)&&(!per.CanBrowse);
boolb2=(pType==PermissionType.Add)&&(!per.CanAdd);
boolb3=(pType==PermissionType.Update)&&(!per.CanUpdate);
boolb4=(pType==PermissionType.Delete)&&(!per.CanDelete);

if(b1||b2||b3||b4)
{
this.permissionHelper.OnHaveNoPermission(pType,response);
return;
}

response.Redirect(destUrl);
}

///<summary>
///如果权限满足,则执行目标方法
///</summary>
publicvoidExcute(IPermissionper,intpType,HttpResponseresponse,DelegatedestMethod,object[]args)
{
boolb1=(pType==PermissionType.Browse)&&(!per.CanBrowse);
boolb2=(pType==PermissionType.Add)&&(!per.CanAdd);
boolb3=(pType==PermissionType.Update)&&(!per.CanUpdate);
boolb4=(pType==PermissionType.Delete)&&(!per.CanDelete);

boolb5=false;

if((pType!=PermissionType.Browse)&&(pType!=PermissionType.Add)&&(pType!=PermissionType.Update)&&(pType!=PermissionType.Delete))
{
b5
=!this.permissionHelper.VerifyCustomPermission(per,pType);
}

if(b1||b2||b3||b4||b5)
{
this.permissionHelper.OnHaveNoPermission(pType,response);
return;
}

destMethod.DynamicInvoke(args);
}
#endregion
}

Excute方法之所以重载是因为,如果条件满足,应用通常是两种反应:
(1)转到用户想进入的某个page
(2)执行用户希望的某个方法/操作

实际上,紧紧使用第二个Excute已经可以包含一切了,第一个Excute是为了简化通常情况(进入的某个page)的操作。
有了PermissionController,我们的工作会轻松很多,比如,在没有使用PermissionController的时候,我们经常这样做:
privatevoidDataGrid1_ItemCommand(objectsource,System.Web.UI.WebControls.DataGridCommandEventArgse)
{
stringid=e.Item.Cells[0].Text;
if(e.CommandName=="ButtonUpdate")
{
if(!SessionHelper.CreateInstance(this.Session).UserRoleCollection.AdminSubSystemPermission.CanUpdate)
{
this.Response.Redirect("../ErrorInfoForm.aspx");
return;
}

this.Response.Redirect("CQProjectPhaseForm.aspx?ID="+id);
}
}

使用PermissionController后,主要这样就可以了:
privatevoidDataGrid1_ItemCommand(objectsource,System.Web.UI.WebControls.DataGridCommandEventArgse)
{
stringid=e.Item.Cells[0].Text;

GeneralPermissiongp=SessionHelper.CreateInstance(this.Session).UserRoleCollection.AdminSubSystemPermission;
if(e.CommandName=="ButtonUpdate")
{
Global.PermissionController.Excute(gp,MGPPermissionType.Update,this.Response,"CQProjectPhaseForm.aspx?ID="+id);
}

原来需要六行代码,现在一行就搞定了。(关于SessionHelper的信息,请参见这里

我们小结一下,看看使用PermissionController还会带来哪些好处:
(1)将原来分散的权限控制,全部集中起来了。
(2)应用中对权限控制所需的代码量大大减少。
(3)如果要改变系统针对权限不满足时所进行的动作,只要改变IPermissionHelper.OnHaveNoPermission方法的实现就可以了,而不是要到每个page中修改。
(4)扩展/修改权限类别非常方便。

你可以把PermissionController的实现和相关接口定义拷贝到自己的类库中,然后在项目中使用。也可以直接使用ESFramework(V0.1+)的ESFramework.Web.PermissionController类。

欢迎你和我讨论关于权限控制的更多更好的解决方案,agilesoft@163.com

分享到:
评论

相关推荐

    PHP权限管理系统.zip

    PHP权限管理系统源码 PHP权限管理系统源码 PHP权限管理系统源码 PHP权限管理系统源码 PHP权限管理系统源码 PHP权限管理系统源码 PHP权限管理系统源码 PHP权限管理系统源码 PHP权限管理系统源码 PHP权限管理...

    c#通用版权限管理系统

    主要功能有:权限管理、角色管理、部门管理、用户管理、公司管理、模块管理、系统设置。适用 OA、财务、人力等办公软件系统 的二次开发,以关键字(Key)的方式来定义系统的权限,使系统权限分配更加贴合企业需求。...

    PHP权限管理系统源码

    实现了基本的权限管理,本系统是基于权限节点进行认证,可控制菜单显示隐藏,基于角色控制权限节点。 1、前端框架:layui2.5.6 2、后端框架:ThinkPHP5.1.39LTS 3、后端界面基于layuimini 权限管理系统安装教程: 1...

    基础权限管理系统基础权限管理系统

    基础权限管理系统基础权限管理系统基础权限管理系统基础权限管理系统基础权限管理系统基础权限管理系统基础权限管理系统基础权限管理系统基础权限管理系统

    权限系统概要-权限系统概要

    权限系统概要 权限系统概要 权限系统概要 权限系统概要 权限系统概要 权限系统概要 权限系统概要 权限系统概要

    php权限管理系统

    根据权限管理系统流程图可得到系统功能呢如下: (1) 游客注册功能:游客可以通过注册成为会员,从而进入系统。 (2) 普通用户功能:在前台界面中,只要注册成功的普通用户就可以进行会员的相关操作。 (3) 管理...

    通用权限管理系统 通用权限管理系统

    通用权限管理系统通用权限管理系统通用权限管理系统通用权限管理系统通用权限管理系统通用权限管理系统通用权限管理系统

    基于SpringBoot + MyBatis + Layui的后台权限管理系统.zip

    基于SpringBoot + MyBatis + Layui的后台权限管理系统。代码简洁易懂、界面美观大方,内部封装了权限管理系统常用的全部功能,可直接作为快速开发JavaWeb项目的脚手架使用。 基于SpringBoot + MyBatis + Layui的...

    8个权限管理系统源码合集【含数据库】.zip

    8个权限管理系统源码合集【含数据库】: Jaoso新闻文章发布系统final+Struts+Spring+Hibernate.rar java web 系统权限设计 源码.rar JAVA权限管理系统2.rar Java酒店管理系统.rar struts+hibernate权限管理系统_...

    基于SpringBoot+JWT+Vue的权限管理系统.zip

    基于SpringBoot+JWT+Vue的权限管理系统源码,基于SpringBoot+JWT+Vue的权限管理系统基于SpringBoot+JWT+Vue的权限管理系统基于SpringBoot+JWT+Vue的权限管理系统基于SpringBoot+JWT+Vue的权限管理系统基于SpringBoot...

    java 后台权限管理系统

    是一个简单高效的后台权限管理系统。项目基础框架采用全新的Java Web开发框架 —— Spring Boot2.0.4,消除了繁杂的XML配置,使得二次开发更为简单;数据访问层采用Mybatis,同时引入了通用Mapper和PageHelper插件,...

    Winform通用框架之权限管理系统界面

    Winform通用框架之权限管理系统---------菜单,开发界面。 在csdn一篇博客中看到文章Winform通用框架之权限管理系统,但是只有文章没有源码就是耍流氓。于是自己写了出来,可用于所有管理系统的开发框架。 软件的...

    基于SpringBoot+vue的前后端分离权限管理系统,界面美观,代码简洁易读。

    基于SpringBoot+vue的前后端分离权限管理系统,界面美观,代码简洁易读。 基于SpringBoot+vue的前后端分离权限管理系统,界面美观,代码简洁易读。 基于SpringBoot+vue的前后端分离权限管理系统,界面美观,代码...

    用户权限管理系统 ppt

    用户权限管理系统,是PPT,可以了解用户权限管理系统的设计。仅供学习。

    权限管理系统.rar权限管理系统.rar

    权限管理系统.rar权限管理系统.rar

    通用权限管理系统前端页面+html5+css3+javascript+vue+elementui

    只需在数据库中配置权限信息,系统就可以动态地读取角色和权限信息,并由管理员将二者关联起来。前端页面只需在该系统的基础上添加,并分配好权限即可。该系统使用动态路由,使得前端页面的添加变得更加容易。可用于...

    PHP通用权限管理系统源码,PHP通用权限管理系统源码

    PHP通用权限管理系统源码,PHP通用权限管理系统源码,PHP通用权限管理系统源码,PHP通用权限管理系统源码,

    系统权限设计详解.doc

    所以,系统中就提出了对“组”进行操作的概念,将权限一致的人员编入同一组,然后对该组进行权限分配。 • 权限管理系统应该是可扩展的。它应该可以加入到任何带有权限管理功能的系统中。就像是组件一样的可以被不断...

    通用权限管理系统

    通用权限管理系统, BS 结构的。 含: 1,用户管理 2,登录验证 3,权限管理

    通用权限管理系统(mysql)

    通用权限管理系统是一套脱离用户系统、脱离栏目(版块、功能)系统的,权限管理体系,使用时可任意搭配现有的用户及其其他相关系统实现无缝整合。 系统采用权限组的概念,用户可属于任意一个组或多个组,组之间的...

Global site tag (gtag.js) - Google Analytics