权限系统设计与使用说明本文介绍一个通用权限系统的设计和使用,该系统可以满足99%的权限需求,该模块已经做成dll,可以供任何系统调用。本文主要介绍如下内容: 问题提出解决方案设计步骤界面操作对外接口问题提出
我们知道权限是应用系统不可缺少的部分,每个系统都有自己的权限管理,有的系统权限设计的比较细,有的设计的比较“粗糙”。每个系统对权限的要求也不同,目前市场上的软件权限设计的五花八门,但没有一个统一的标准,也没发现几个拿来就可以用的。既然应用软件都需要权限,那么为什么不把权限做成一个公用的模块,供任何系统调用呢?处于这个目的我设计开发了一套Delphi版的权限管理,同时系统日志也是可以做成公用模块的。下面介绍一下权限管理的解决方案。解决方案
权限管理以人、组和操作为管理要素,人即系统登录用户,所有的人分组管理,对组划分配操作权限。操作细化到每一个界面元素(一个具体操作,如按钮、菜单),每个操作对应一个唯一的权限码(细化到界面元素的好处是可以应对任何权限需求,没有比这个要求更苛刻的了)。在用户点按钮或者菜单的时候进行权限判断。建立组的概念是为了方便管理,一个人可隶属于多个组,对组赋予某一操作权限后,该组下的所有人都会有该权限,一组为单位分配权限,是不是很方便?人、组和操作之间的关系如下图:
设计步骤
根据上面的权限方案,在对系统进行权限设计的时候,遵循以下步骤:第一步:为系统划分模块、功能和操作,这个过程一般在系统设计阶段已经完成,但是权限设计与具体业务无关,即使在系统设计的时候划分好了功能模块,也可以在权限系统中重新划分。划分模块、功能和操作的目的是为了对操作码分类管理。具体管理的方式是模块码-〉功能码-〉操作码,三种编码采用如下编码方式: 第二步:对操作用户分组管理,组也可以理解为角色,一个组代表具有一类操作权限的集合,系统中可以有很多组,对租的划分遵循同等权限级别的为一组,尽量避免重叠划分,划分的规则一般与使用系统的客户所属部门有关,例如,可以建立如下组:销售部,采购部,办公室,经理等。划分好组后,向组中添加组员(即具体的操作人员),一个组员可以隶属于多个组。第三步:为组分配权限,建立组与操作码之间的关系,一个组可以有任意多个操作码,一个操作码可以分配给多个组,一旦为组分配了权限,组中的成员也就具有了该权限。界面操作
下面介绍一下权限系统的具体操作。主界面
 图表 1权限管理界面第一步:为系统划分模块、功能和操作
 图表 2右键菜单操作 
图表 3新建/修改模块 
图表 4新建/修改功能 
图表 5新建/修改操作第二步:对操作用户分组管理用户和组的操作界面 
图表 6本地用户和组用户管理的操作界面 
图表 7新建用户 
图表 8用户属性 
图表 9用户属性组的操作界面 
图表 10新建组 
图表 11组常规属性 
图表 12组成员属性 
图表 13添加用户第三步:为组分配权限 
图表 14分配权限查看组已有权限 见图11。对外接口
权限系统采用Delphi7+Sqlserver2000编写,生成的动态库名为UserMan.dll,提供两个对外接口函数,一个调用权限管理的函数,一个是权限判断函数。权限管理函数函数申明:procedure Load_UserMan(ADOConn: TADOConnection; AppHandle: THandle); stdcall; export;参数说明:ADOConn:打开的数据库连接AppHandle:调用权限管理的应用程序的句柄。调用实例:procedure Load_UserMan(ADOConn: TADOConnection; AppHandle: THandle); stdcall; external 'UserMan.dll';procedure TfrmDxMain.N1Click(Sender: TObject);begin {调用权限管理}   Load_UserMan(dmDxData.DBConnection,Application.Handle); end; 权限判断函数函数申明:Function IsPower(ADOConn: TADOConnection;Const; PowerCode,UsrCode:string):Boolean;stdcall; export;参数说明:ADOConn:打开的数据库连接PowerCode:当前操作码UsrCode:当前用户调用实例:Function  IsPower(ADOConn: TADOConnection;Const PowerCode,UsrCode:string):Boolean;stdcall; external 'UserMan.dll';procedure TfrmDxMain.N1Click(Sender: TObject);begin {调用权限管理}  if not IsPower(dmDxData.DBConnection,'000000', 'leg') then  begin    WarningDlg('没有操作权限请与管理员联系!该操作码000000'+',用户帐号leg','提示');    Exit;  end; end;

解决方案 »

  1.   

    to rodgerkong,1,不能为用户单独赋权,设计的时候考虑到登录系统的人一般是属于一定角色的,而且登录系统的人必须要经过赋权。
    2,组权限冲突,比如某一操作在组一中被禁止,在组二中许可,用户同时属于组一和组二,那么这个这用户也有该权限,所以在权限分配的时候注意这个问题,可以采取再创建一个组的方式来解决。
    3,目前未达到这个灵活度,你说的这个需求在现实中可能会遇到,但为了统一权限管理,有系统管理员来分配权限,以免出乱,没有实现这个功能。to baseyueliang,是对具体的操作授权,选中整个模块授权时会把模块下的所有操作赋权。
      

  2.   

    我说的三点,在一般的权限系统中都没有实现,但是实际应用中体现比较突出的几个问题。
    实际上要实现也并不是十分复杂,但是需要在权限系统规划阶段就考虑进去,否则很难进行扩展和升级。
    设计出比较灵活,适应面广的权限与认证系统要考虑的细节很多,C/S环境和B/S环境下要面对的问题又不一样,所以能涉猎这方面的内容确实是个锻炼。给楼主加油~
      

  3.   

    to rodgerkong,你说的的这三个问题特别是第三个问题,能说一下在那些系统中有这种要求吗?给举个例子,好加深印象。
      

  4.   

    gaze.
    rodgerkong说得3个问题,
    1.我们以前的系统有做过,大概是做个单选按钮,可以选择是“按角色授权”还是“单独授权”
    2.我觉得可以做个配置,可以让用户选择权限是最大化还是最小化,即用户的权限是他所属的组的权限的并集还是交集
    3.比如新增××的一个权限,系统管理员将他分配给各部门的管理员,各部门的管理员再将他分配给自己部门内需要新增的人,比如文书什么的。
      

  5.   

    gaze.
    rodgerkong说得3个问题,
    1.我们以前的系统有做过,大概是做个单选按钮,可以选择是“按角色授权”还是“单独授权”
    2.我觉得可以做个配置,可以让用户选择权限是最大化还是最小化,即用户的权限是他所属的组的权限的并集还是交集
    3.比如新增××的一个权限,系统管理员将他分配给各部门的管理员,各部门的管理员再将他分配给自己部门内需要新增的人,比如文书什么的。
      

  6.   

    楼上的说得基本上对。权限系统要细说起来可能会是长篇大论,既要考虑接口对于模块开发人员的便利性,又要考虑对于用户进行授权操作的实用性。第一个问题我只说一个原则,实现起来应当不难,就是:个人权限高于角色权限。假设有模块操作M1A1, M1A2, M2A1, M3A1;有角色R1=(M1A1, M1A2, M3A1);有用户U1属于R1;如果不对用户U1单独指派权限,那么U1=R1=(M1A1, M1A2, M3A1);如果为U1单独许可M2A1,同时禁止M1A2,那么U1=R1+M2A1-M1A2=(M1A1, M2A1, M3A1);再假设有角色R2=(M1A1, M1A2),现将U1的所属改为R2,那么U1=R2+M2A1-M1A2=(M1A1, M2A1)。第二个问题解决起来可能复杂一些,需要在单项权限定义的时候附加声明一个属性:优先规则,指明当权限发生冲突时,使用何种优先规则,针对二值权限,只要定义许可优先或是禁止优先就可以了,注意:这个优先规则只适用于解决同级权限冲突,比如用户同时属于两个平级的角色。例如对于上例中的所有模块操作权限都默认为定义为许可优先,只有M1A2定义为禁止优先,设R1=(M1A2, M2A1),R2=(M2A1, M3A1),U1同时属于R1与R2,并且U1单独许可M1A1,则U1=(R1[仲裁]R2)+M1A1=((M1A2, M2A1)[仲裁](M2A1, M3A1))+M1A1=(M2A1, M3A1)+M1A1=(M2A1, M3A1, M1A1)。注意:仲裁时,由于R2不具备M1A2的许可,也就是禁止,与R1的M1A2许可相冲突,按照M1A2的优先仲裁规则,判为禁止,所以结果中没有M1A2的许可;同时R2中的M3A1使用许可优先,从而获得许可。最后再叠加用户权限,得到结果。第三个问题就更复杂了,需要对每个需要委托的权限项目增加允许委托的属性,相当于是针对权限本身的权限,而且由于授权是针对两个主题的操作(用户和功能),所以用户(包括角色)也需要定义委托属性,这样才能完整地实现权限委托。权限委托的实例可以这样理解,假设有一个跨国机构,使用一个极其复杂的业务系统,管理层次分为很多层,各个国家地区的人事调动极为频繁,使用的语言多种多样,如果都依靠总部的系统管理员去授权,工作量极大,而且由于不了解各个业务部门的实际操作,授权不好掌握。如果能由各个国家分部的管理员接管本国内部的权限管理,那将会方便很多,同样,国家一级的管理员也只需要将地区或部门特定使用的功能委托给当地的管理员,而部门的主管在经过适当的权限委托会后,可以自如的对自己所掌握的功能与人员进行权限分配,这样层层委托的结果是:减轻系统管理人员的负担和责任,增加系统安全的反应速度和准确度。另外,我们所理解的权限项目有时也并不限于二值情况(许可、禁止),有时可能会有多值情况,比如,对于多级结构的组织,定义查看权限时,可能会用到以下权限项目:禁止查看、仅查看属于本人的数据、仅查看属于本部门的数据、仅查看属于本区域的数据、查看组织内的所有数据,这是典型的多值权限。引入多值权限,在提高系统灵活度的同时也将大大提高系统的设计难度,许多问题都需要重新考虑。当然,这种情况比较少见,而且有时也可以通过拆分为二值权限的方法进行简化,这里只是提出一个可能会遇到的问题,供大家参考。
      

  7.   

    rodgerkong说的不错,一般的业务系统权限方面都涉及到了权限想下分配的问题.
    LZ的源代码还是建议回去再XG再说
      

  8.   

    又看了一下主贴,再提醒楼主一个问题:似乎整个界面是嵌入在dll中的,通过一个接口函数显示界面。作为一个想商业化的局部模块,这样会大大限制客户群,因为别人的软件界面风格也许完全是另一种模式,交互方法也可能完全不同。建议扩展dll中导出的API,使用户能够使用数据作为接口,而不是界面,这样可以增加这套系统的灵活性。