精华内容
下载资源
问答
  • 权限设计

    2019-07-13 23:51:34
    一、令人头疼的权限设计 设计师在进行设计时,常常会抽象出对产品有诉求的多个角色,再依据角色的特性去梳理使用场景并设计。 当角色之间的使用场景不冲突,不需要隔离时,我们会综合考虑这些角色的使用场景来设计...

     

    一、令人头疼的权限设计

    设计师在进行设计时,常常会抽象出对产品有诉求的多个角色,再依据角色的特性去梳理使用场景并设计。

    当角色之间的使用场景不冲突,不需要隔离时,我们会综合考虑这些角色的使用场景来设计解决方案。比如:网易云音乐同时为需要听歌和听电台的用户,提供所有的功能。

    当这些角色的使用场景完全不重叠、流程对立时,我们会设计完全独立的两套系统,如滴滴的司机端和乘客端。

    但除了以上两种情况,在大多数 B 端产品中,基于流程公正性、信息安全性等因素考虑,各个角色的使用场景是部分通用,部分隔离的,这时候就需要引入「权限系统」了。

    设计师有时会对角色权限系统有一丝畏难情绪。

    • 一方面因为角色权限系统的配置作为一个非常后台的管理功能,在竞品调研过程中很难通过上帝视角去解剖其中逻辑,自己琢磨又较难透彻;
    • 另一方面对于角色权限系统,做好了并不能代表设计能力有多优秀,但一旦没做好就会导致整个流程不通、产品崩溃。所以设计师常对权限系统望而却步。

    以下就笔者的几次权限设计经历,提供一些所谓的经验套路。

    二、基于技术模型进行设计-RBAC模型

    进行设计前,最好能够理解技术模型。在业界接受度较高的功能权限模型是 RBAC(Role-Based Access Control)模型,其基本理念是将「角色」这个概念赋予用户,在系统中用户与权限之间通过角色进行关联,以这样的方法来实现灵活配置。以下就模型与设计相关的几点做一下简单介绍。

    1. 基本的RBAC模型

    如果没有角色的概念,系统中每加入一个用户,就需要为这个用户配置一遍权限,下图是 wiki 中直接为用户权限管理方式,可以看出管理成本巨大。

    而引入「角色」概念后,如下图即是 RBAC 模型中最基本的模型:用户与角色可为多对一或多对多的关系,当一个用户的角色为多对多时,当前用户的权限是多个角色的并集。

    此时只需要为角色赋予权限,能够大大减轻管理负担,同时将用户与权限解耦,提供更大的灵活性。

    2. 引入用户组概念的RBAC模型

    在大型平台的应用上,试想如果用户量上万,新增一个角色时,可能需要为大量用户都分配一遍新的角色,工程量仍然巨大,此时即可以引入用户组的概念。如果部分用户的使用场景是相对一致和基础的,我们可以把这些用户打包成一个组,基于这个组的对象进行角色和权限的赋予。

    同理如果权限较多时也会存在一样的问题,处理方式是引入权限组的概念,将使用场景相对固定的一组功能或权限打包成组赋予角色。但是一般来讲一个系统中权限功能的体量是相对有限和可控的,所以实际应用中对权限组的使用较少。

    下图所示为 mac 系统中运行添加用户组,并以用户组为单位配置权限。

    需要注意的是即使有用户组或权限组的存在,也可以允许用户或权限与角色直接关联,这个可以视具体业务情况而定。

    3. 角色继承的RBAC模型

    在一个业务场景中,如果角色需区分:设计主管、设计组长、设计成员,并且管理方式为向下兼容时,则需使用角色继承的 RBAC 模型。上层角色继承下层角色的全部权限,且可额外赋予权限。

    此时除了对角色进行定义,还需要管理角色间的关系,通过关系来体现角色的层级关系,从而达到继承权限的效果。角色的继承关系主要有两种:树形图和有向无环图。

    继承关系常常来源于公司团队的组织结构,此时常将角色与组织结构进行关联达到继承角色模型的效果。如下图所示的赵同学,其角色是「三级团队负责人」,与其并列的小组中有多个「三级团队负责人」的角色,但依附于左侧的组织结构树,各级负责人仅有查看和操作自己下属子节点的权限。

    4. 限制的RBAC模型

    在一个产品或系统中,部分角色可能是需要隔离的、不允许被同时赋予一个人的。跟大家熟知的不能既是「运动员」又是「裁判员」一个道理。

    因此,对于众多角色中的一组,只能是单选的关系,但多组角色之间可以共同存在。如下图中,一个用户可以既为设计师又为管理员,但在设计师角色组中仅能被赋予一个角色,在管理员角色组中也仅能被赋予一个角色。

    此外,限制还有可能是数量上的,比如一个产品组中必须有且只有一个管理员,不允许删除或再分配管理员角色,仅允许将负责人角色变更。

    限制的模型不仅仅对分配过程产生影响,有时即使拥有了多种角色,因为不同的角色对同一个功能的使用方式或数据会产生冲突,所以使用时也需要进行限制。如下图所示为同一时间仅允许以一个身份登录。

    根据不同的业务需求,限制的形式很多。需要注意的是不能仅依赖后端限制,而是要在前端展示清晰的规则和恰当的限制,避免用户出错和沮丧。

    三、权限的拆分与设计

    通过 RBAC 模型已经能够很好的搭建起用户、角色与权限之间的关系了。但具体是什么样的关系,以及「权限」这个抽象的概念具体如何规划?

    这些都需要分析清楚才能进一步设计出完善的权限系统。

    首先需要知道,一般产品的权限由页面、操作和数据构成。页面与操作相互关联,必须拥有页面权限,才能分配该页面下对应的操作权限。数据可被增删改查。

    整体关系如下图所示:

    因此,在设计之初我们就需要考虑到未来可能区分角色的地方,尽量解耦、模块化。对于技术来说,每一个页面模块、每一个操作都最好使用独立的接口。对于设计来说,需要保障所有角色因为权限而屏蔽掉部分操作和数据后,页面和流程仍能体验流畅。

    保证初期设计支持后,配置权限时,还需要注意以下几点:

    1. 确定是否支持前端配置

    如果角色和权限相对固定,则一般将角色与权限的关系可以写在后台,改动时需要后端变更且重新上线。这种情况适用于公司内部系统等只有一个使用主体的系统。

    如果需要自定义角色或者每个角色在不同使用者的场景下有不同的权限,则需要将角色的定义、角色与权限之间的配置体现在「前端用户配置页面」。这种情况适用于有频繁变动的自定义角色权限,和有租户体系的系统。

    2. 以基本单元拆分,以业务逻辑配置

    一般可将每个对象的「增、删、改、查」各自作为一个基本的权限单元。打个比方,在「人员管理」中,查看人员列表、添加人员、删除人员、编辑人员信息最好拆分为4个权限单元。在技术和设计上,我们希望能尽量做到解耦和模块化。

    但是在业务层面有些操作却是一体的。这些不能拆开的权限在「前端用户配置页面」中建议打包成一个整体提供配置。例如:如果我们确定在系统的现有和未来业务中,仅分为普通成员有「人员管理」的查看权限,管理员有操作权限,则可将「增、删、改」三个基本权限单位合并为「操作」权限进行配置。

    3. 页面权限优先于操作和数据权限

    必须配置了页面模块权限后,才能配置当前页面模块下具体的操作权限,以及页面模块的数据展示权限。

    4. 查看权限优先于增删改权限

    正常情况下,一定要先能查看某个模块或操作,其它的增删改操作才有意义。因此在设计时,应在获取查看权限前限制其它权限的配置,或者配置其它权限时默认赋予查看权限。

    5. 角色与权限的多种关系

    角色与权限的关系不仅是单纯「是/否关系」,还包括以某种限制进行操作,和以某种程度访问数据。

    例如在「人员管理」中:

    • 数据范围:用户拥有查看人员列表的权限,但仅能查看自己所在的团队;
    • 数据边界限制(上限等):添加人员时不能超过20个等。
    • 数据字段:HR 能查看人员列表中包括职级、薪资等字段,其它角色仅能查看姓名邮箱等字段;

    6. 角色与权限的设计表达

    在传达一个系统的权限设计规则时,设计师常常习惯用主观最直接的方式表达想法,如用「当……时,就……」的句式来表达。但一个平台中涉及的权限规则是非常多的,当通篇以这样的形式描述时,表达对象将很难理解。

    正确的描述方式:更清晰的是基于开发的语言,和技术模型的结果进行表达。将各角色与权限单元绘制成网格,每个交叉点网格中描述该角色与权限的数据关系和限制。

    如下图所示:

    四、需要注意的Tips

    1. 隐形的admin

    在可自定义角色和权限的系统中,一般需要预留一个 admin 角色来进行系统的初始配置,用于添加首批的业务人员和配置基本的角色。

    有的系统中允许存在上帝视角的 admin 角色,则其可以作为「超级管理员」显示在角色配置的列表中。有的系统中不允许这种角色存在,则可将这种角色设置为隐形的状态,仅赋予维护系统的工作人员。

    2. 初始权限的赋予

    对于允许用户自行加入的系统,需要设定一至多个默认的角色,有时可以是仅有最基础权限的「游客」角色。

    初始权限还可以与用户既有的某些数据字段进行关联,如添加用户时获取到用户的岗位为「设计师」,则直接赋予「设计师」角色的权限。

    3. 人员管理中对自己的处理

    在人员管理中,管理员角色处理自己时需要额外注意。因为如果修改或删除了自己角色后,可能导致系统没有管理角色,从而无法添加其他成员和正常运行。设计时可添加判断,当自己为唯一管理角色时,禁止编辑和删除。

    4. 无页面权限的提示

    虽然可以通过页面权限限制直接隐藏当前用户没有权限的页面,但不能排除用户获取到权限外的 url 地址。当用户意外访问到没有权限的页面时务必提供「无权限」的提示,避免用户认为系统 bug。

    总结

    总结一下,整个权限系统设计就是定义各个节点和节点间关系的过程。

    节点包括:

    • 用户;
    • 用户组;
    • 角色;
    • 角色组;
    • 权限(页面、操作、数据);
    • 权限组(页面、操作、数据)。

    关系包括:

    • 是/否关系;
    • 继承关系;
    • 限制关系(互斥、范围限制、边界限制、字段限制……);

    梳理清楚所有逻辑后,通过灵活定义节点和组合各节点之间的关系,便能够轻松完成角色权限设计的100种解法。

    「后台设计好文」

     

    非特殊说明,本文版权归原作者所有,转载请注明出处 
    本文地址:https://www.uisdc.com/100-solutions-for-character-permission-design

    展开全文
  • 权限设计

    2008-03-26 11:11:00
    但凡涉及多用户不同权限的网络或者单机... 权限设计通常包括数据库设计、应用程序接口(API)设计、程序实现三个部分。 这三个部分相互依存,密不可分,要实现完善的权限管理体系,必须考虑到每一个环节可行性与复杂程
    但凡涉及多用户不同权限的网络或者单机程序,都会有权限管理的问题,比较突出的是MIS系统。
    下面我要说的是MIS系统权限管理的数据库设计及实现,当然,这些思路也可以推广开来应用,比如说在BBS中用来管理不同级别的用户权限。
    权限设计通常包括数据库设计、应用程序接口(API)设计、程序实现三个部分。
    这三个部分相互依存,密不可分,要实现完善的权限管理体系,必须考虑到每一个环节可行性与复杂程度甚至执行效率。
    我们将权限分类,首先是针对数据存取的权限,通常有录入、浏览、修改、删除四种,其次是功能,它可以包括例如统计等所有非直接数据存取操作,另外,我们还可能对一些关键数据表某些字段的存取进行限制。除此,我想不出还有另外种类的权限类别。
    完善的权限设计应该具有充分的可扩展性,也就是说,系统增加了新的其它功能不应该对整个权限管理体系带来较大的变化,要达到这个目的,首先是数据库设计合理,其次是应用程序接口规范。
    我们先讨论数据库设计。通常我们使用关系数据库,这里不讨论基于Lotus产品的权限管理。
    权限表及相关内容大体可以用六个表来描述,如下:
    1 角色(即用户组)表:包括三个字段,ID,角色名,对该角色的描述;
    2 用户表:包括三个或以上字段,ID,用户名,对该用户的描述,其它(如地址、电话等信息);
    3 角色-用户对应表:该表记录用户与角色之间的对应关系,一个用户可以隶属于多个角色,一个角色组也可拥有多个用户。包括三个字段,ID,角色ID,用户ID;
    4 限制内容列表:该表记录所有需要加以权限区分限制的数据表、功能和字段等内容及其描述,包括三个字段,ID,名称,描述;
    5 权限列表:该表记录所有要加以控制的权限,如录入、修改、删除、执行等,也包括三个字段,ID,名称,描述;
    6 权限-角色-用户对应表:一般情况下,我们对角色/用户所拥有的权限做如下规定,角色拥有明令允许的权限,其它一律禁止,用户继承所属角色的全部权限,在此范围内的权限除明令禁止外全部允许,范围外权限除明令允许外全部禁止。该表的设计是权限管理的重点,设计的思路也很多,可以说各有千秋,不能生搬硬套说某种方法好。对此,我的看法是就个人情况,找自己觉得合适能解决问题的用。
    先说第一种也是最容易理解的方法,设计五个字段:ID,限制内容ID,权限ID,角色/用户类型(布尔型字段,用来描述一条记录记录的是角色权限还是用户权限),角色/用户ID,权限类型(布尔型字段,用来描述一条记录表示允许还是禁止)
    好了,有这六个表,根据表六,我们就可以知道某个角色/用户到底拥有/禁止某种权限。
    或者说,这么设计已经足够了,我们完全实现了所需要的功能:可以对角色和用户分别进行权限定制,也具有相当的可扩展性,比如说增加了新功能,我们只需要添加一条或者几条记录就可以,同时应用程序接口也无须改动,具有相当的可行性。但是,在程序实现的过程中,我们发现,使用这种方法并不是十分科学,例如浏览某个用户所拥有的权限时,需要对数据库进行多次(甚至是递归)查询,极不方便。于是我们需要想其它的办法。使用过Unix系统的人们都知道,Unix文件系统将对文件的操作权限分为三种:读、写和执行,分别用1、2、4三个代码标识,对用户同时具有读写权限的文件被记录为3,即1+2。我们也可以用类似的办法来解决这个问题。初步的想法是修改权限列表,加入一个字段:标识码,例如,我们可以将录入权限标识为1,浏览权限标识为2,修改权限标识为4,删除权限标识为8,执行权限标识为16,这样,我们通过权限累加的办法就可以轻易的将原本要分为几条记录描述的权限放在一起了,例如,假定某用户ID为1,库存表对应的限制内容ID为2,同时规定角色类型为0、用户类型为1,我们就可以将该用户具有录入、浏览、修改、删除库存表的权限描述为:2,15,1,1。
    确实很简单,不是吗?甚至还有更过激的办法,将限制内容列表也加上一列,定义好标识码,这样,我们甚至可以用简单的一条记录描述某个用户具有的对全部内容所具有的全部权限了。当然,这样做的前提是限制内容数量比较小,不然,呵呵,2的n次方递增起来可是数量惊人,不容易解析的。
    从表面上看,上述方法足以达到实现功能、简化数据库设计及实现的复杂度这个目的,但这样做有个弊端,我们所涉及的权限列表不是相互独立而是互相依赖的,比如说修改权限,其实是包含浏览权限的,例如,我们可能只是简单的设置用户对库存表存取的权限值为录入+修改+删除(1+4+8=13),但事实上,该用户具有(1+2+4+8=15)的权限,也就是说,在这种方案中,13=15。于是当我们调用API询问某用户是否具有浏览权限时,就必须判断该用户是否具有对该数据表的修改权限,因此,如果不能在程序中固化权限之间的包含关系,就不能利用应用程序接口简单的做出判断。但这与我们的目的“充分的可扩展性”矛盾。
    这个问题如何解决?我想到了另外一种设置标识码的方法,那就是利用素数。我们不妨将录入、浏览、修改、删除、执行的基本标志码定为2,3,5,7,11,当遇到权限互相包含的时候,我们将它的标识码设定为两个(或多个)基本标志码的乘积,例如,可以将“修改”功能的标志码定为3*5=15,然后将所有的权限相乘,就得到了我们需要的最终权限标识值。这样,我们在询问用户是否具有某项权限的时候,只需要将最终的值分解成质因子,例如,我们可以定义一个用户具有录入+修改+删除库存表的权限为 2*15*7=2*3*5*7,即表示,该用户具有了对库存表录入+浏览+修改+删除权限。
    当然,对权限列表我们使用上述方法的前提是权限列表记录条数不会太多并且关系不是十分复杂,否则,光是解析权限代码就要机器忽悠半宿:)
    我希望以上的分析是正确且有效的(事实上,我也用这些的方法在不止一套系统中实现),但无论如何,我觉得如此实现权限管理,只是考虑了数据库设计和应用程序接口两部分内容,对于实现,还是显得很费劲。因此,我恳请有过类似设计、实现经验的同志们提出建设性的意见和修改建议。
    另外,关于数据库设计的思路还有使用二维表的,这将在以后的时间里讨论,关于应用程序接口的设计和实现我也将在利用另外篇幅和大家共同探讨,代码将用类C语法实现
    为了设计一套具有较强可扩展性的用户认证管理,需要建立用户、角色和权限等数据库表,并且建立之间的关系,具体实现如下。
    用户
    用户仅仅是纯粹的用户,用来记录用户相关信息,如用户名、密码等,权限是被分离出去了的。用户(User)要拥有对某种资源的权限,必须通过角色(Role)去关联。
    用户通常具有以下属性:
    ü         编号,在系统中唯一。
    ü         名称,在系统中唯一。
    ü         用户口令。
    ü         注释,描述用户或角色的信息。
    1.2 角色
    角色是使用权限的基本单位,拥有一定数量的权限,通过角色赋予用户权限,通常具有以下属性:
    ü         编号,在系统中唯一。
    ü         名称,在系统中唯一。
    ü         注释,描述角色信息
    1.3 权限
           权限指用户根据角色获得对程序某些功能的操作,例如对文件的读、写、修改和删除功能,通常具有以下属性:
    ü         编号,在系统中唯一。
    ü         名称,在系统中唯一。
    ü         注释,描述权限信息
    1.4 用户与角色的关系
    一个用户(User)可以隶属于多个角色(Role),一个角色组也可拥有多个用户,用户角色就是用来描述他们之间隶属关系的对象。用户(User)通过角色(Role)关联所拥有对某种资源的权限,例如
    l         用户(User):
    UserID      UserName      UserPwd
    1                   张三                 xxxxxx
    2                   李四                 xxxxxx    
    ……
    l         角色(Role):
    RoleID           RoleName          RoleNote
           01                  系统管理员       监控系统维护管理员
           02                  监控人员          在线监控人员
           03                  调度人员          调度工作人员
           04                  一般工作人员   工作人员
           ……
    l         用户角色(User_Role):
    UserRoleID           UserID           RoleID           UserRoleNote
    1                       1                   01                  用户“张三”被分配到角色“系统管理员”
    2                        2                   02                  用户“李四”被分配到角色“监控人员”
    3                        2                   03                  用户“李四”被分配到角色“调度人员”
    ……
           从该关系表可以看出,用户所拥有的特定资源可以通过用户角色来关联。
    1.5 权限与角色的关系
    一个角色(Role)可以拥有多个权限(Permission),同样一个权限可分配给多个角色。例如:
    l         角色(Role):
    RoleID           RoleName          RoleNote
           01                  系统管理员       监控系统维护管理员
           02                  监控人员          在线监控人员
           03                  调度人员          调度工作人员
           04                  一般工作人员   工作人员
           ……
    l         权限(Permission):
    PermissionID      PermissionName       PermissionNote
    0001                        增加监控                 允许增加监控对象
    0002                        修改监控                 允许修改监控对象
    0003                        删除监控                 允许删除监控对象
    0004                        察看监控信息       允许察看监控对象
    ……
    l         角色权限(Role_Permission):
    RolePermissionID   RoleID PermissionID RolePermissionNote
    1                             01            0001        角色“系统管理员”具有权限“增加监控”
    2                             01            0002        角色“系统管理员”具有权限“修改监控”
    3                             01            0003        角色“系统管理员”具有权限“删除监控”
    4                             01            0004        角色“系统管理员”具有权限“察看监控”
    5                             02            0001        角色“监控人员”具有权限“增加监控”
    6                             02            0004        角色“监控人员”具有权限“察看监控”
    ……
           由以上例子中的角色权限关系可以看出,角色权限可以建立角色和权限之间的对应关系。
    1.6 建立用户权限
    用户权限系统的核心由以下三部分构成:创造权限、分配权限和使用权限。
    第一步由Creator创造权限(Permission),Creator在设计和实现系统时会划分。利用存储过程CreatePermissionInfo(@PermissionName,@PermissionNote)创建权限信息,指定系统模块具有哪些权限。
    第二步由系统管理员(Administrator)创建用户和角色,并且指定用户角色(User-Role)和角色权限(Role-Permission)的关联关系。

    1)        具有创建用户、修改用户和删除用户的功能: Administrator

     
    l         存储过程CreateUserInfo(@UserName,@UserPwd)创建用户信息;
    l         存储过程ModifyUserInfo(@UserName,@UserPwd)修改用户信息;
    l         存储过程DeleteUserInfo(@UserID)删除用户信息;

    2)        具有创建角色和删除角色的功能: Administrator

     
    l         存储过程CreateRoleInfo(@RoleName,@RoleNote)创建角色信息;
    l         存储过程DeleteRoleInfo(@RoleID)删除角色信息;
    3)Administrator具有建立用户和角色、角色和权限的关联关系功能:
    l         存储过程GrantUserRole(@UserID,@RoleID,@UserRoleNote)建立用户和角色的关联关系;
    l         存储过程DeleteUserRole(@UserRoleID)删除用户和角色的关联关系;
    l         存储过程GrantRolePermission(@RoleID,@PermissionID,@RolePermissionNote)建立角色和权限的关联关系;
    l         存储过程DeleteRolePermission(@RolePermissionID)删除角色和权限的关联关系;
    第三步用户(User)使用Administrator分配给的权限去使用各个系统模块。利用存储过程GetUserRole(@UserID, @UserRoleID output),GetRolePermission(@RoleID,@Role-
    -PermissinID output)获得用户对模块的使用权限。
    1.7 用户认证实现
    当用户通过验证后,由系统自动生成一个128位的TicketID保存到用户数据库表中,建立存储过程Login(@UserID,@UserPwd,@TicketID output)进行用户认证,认证通过得到一个TicketID,否则TicketID为null。其流程图如下:
    图1 Login流程图
    得到TicketID后,客户端在调用服务端方法时传递TicketID,通过存储过程JudgeTicketPermission(@TicketID,@PermissionID)判断TicketID对应的用户所具有的权限,并根据其权限进行方法调用。
    当用户退出系统时,建立存储过程Logout(@UserID)来退出系统。当用户异常退出系统时,根据最后的登陆时间(LastSignTime)确定用户的TickeID,建立存储过程ExceptionLogout(@UserID,@LastSignTime)处理用户的异常退出。
    图2 Logout流程图
    WebService可以采用SoapHeader中写入TicketID来使得TicketID从客户端传递给服务端。.Net Remoting可以采用CallContext类来实现TicketID从客户端传递给服务端。
    2 数据库设计
     
    2.1 数据库表
    图3 数据库关系图
    2.2 数据库表说明
    2.2.1 用户表(Static_User)
    Static_User

    Static_User字段名

     
     

    详细解释

     
     

    类型

     
     

    备注

     
     

    UserID

     
     

    路线编号

     
     

    varchar(20)

     
     

    PK

     
     

    UserName

     
     

    用户名称

     
     

    varchar(20)

     
     

     

     
     

    UserPwd

     
     

    用户密码

     
     

    varchar(20)

     
     

     

     
     

    LastSignTime

     
     

    最后登陆时间

     
     

    datatime

     
     

     

     
     

    SignState

     
     

    用户登陆状态标记

     
     

    int

     
     

     

     
     

    TickeID

     
     

    验证票记录编号

     
     

    varchar(128)

     
     

     

     
     

     

     
     

     

     
     

     

     
     

     

     
     

     

     

     

     
    2.2.2 角色表(Static_Role)
    Static_Role

    Static_User字段名

     
     

    详细解释

     
     

    类型

     
     

    备注

     
     

    RoleID

     
     

    角色编号

     
     

    varchar(20)

     
     

    PK

     
     

    RoleName

     
     

    角色名称

     
     

    varchar(20)

     
     

     

     
     

    RoleNote

     
     

    角色信息描述

     
     

    varchar(20)

     
     

     

     
     

     

     
     

     

     
     

     

     
     

     

     
     

     

     
    2.2.3 用户-角色表(Static_User_Role)
    Static_User_Role

    Static_User字段名

     
     

    详细解释

     
     

    类型

     
     

    备注

     
     

    UserRoleID

     
     

    用户角色编号

     
     

    varchar(20)

     
     

    PK

     
     

    UserID

     
     

    用户编号

     
     

    varchar(20)

     
     

    FK

     
     

    RoleID

     
     

    角色编号

     
     

    varchar(20)

     
     

    FK

     
     

    UserRoleNote

     
     

    用户角色信息描述

     
     

    varchar(20)

     
     

     

     
     

     

     
     

     

     
     

     

     
     

     

     
     

     

     
    2.2.4 权限表(Static_Permission)
    Static_Permission

    Static_User字段名

     
     

    详细解释

     
     

    类型

     
     

    备注

     
     

    PermissionID

     
     

    编号

     
     

    varchar(20)

     
     

    PK

     
     

    PermissionName

     
     

    权限名称

     
     

    varchar(20)

     
     

     

     
     

    PermissionNote

     
     

    全息信息描述

     
     

    varchar(20)

     
     

     

     
     

     

     
     

     

     
     

     

     
     

     

     
     

     

     
    2.2.5 角色-权限表(Static_Role_Permission)
    Static_Role_Permission

    Static_User字段名

     
     

    详细解释

     
     

    类型

     
     

    备注

     
     

    RolePermissionID

     
     

    角色权限编号

     
     

    varchar(20)

     
     

    PK

     
     

    RoleID

     
     

    角色编号

     
     

    varchar(20)

     
     

    FK

     
     

    PermissionID

     
     

    权限编号

     
     

    varchar(20)

     
     

    FK

     
     

    RolePermissionNote

     
     

    角色权限信息描述

     
     

    varchar(20)

     
     

     

     
     

     

     
     

     

     
     

     

     
     

     

     
     
    3 .net技术概要
     
    3.1 WebService SoapHeader
    数据库执行自定义身份验证和授权。在这种情况中,应向服务传递自定义凭据(如用户名和密码),并让服务自己处理身份验证和授权。 将额外的信息连同请求一起传递给 XML Web 服务的简便方法是通过 SOAP 标头。为此,需要在服务中定义一个从 SOAPHeader 派生的类,然后将服务的公共字段声明为该类型。这在服务的公共合同中公开,并且当从 WebServiceUtil.exe 创建代理时可由客户端使用,如下例所示:

     

     

    using System.Web.Services;

     

    using System.Web.Services.Protocols;

     

     

     

    // AuthHeader class extends from SoapHeader

     

    public class AuthHeader : SoapHeader {

     

        public string Username;

     

        public string Password;

     

    }

     

     

     

    public class HeaderService : WebService {

     

        public AuthHeader sHeader;

     

        ...

     
    }
    服务中的每个 WebMethod 都可以使用 SoapHeader 自定义属性定义一组关联的标头。默认情况下,标头是必需的,但也可以定义可选标头。SoapHeader 属性指定公共字段的名称或者 Client 或 Server 类的属性(本标题中称为 Headers 属性)。在为输入标头调用方法前,WebService 设置 Headers 属性的值;而当方法为输出标头返回时,WebService 检索该值。

    [WebMethod(Description="This method requires a custom soap header set by the caller")]

     

    [SoapHeader("sHeader")]

     

    public string SecureMethod() {

     

     

     

    if (sHeader == null)

     

    return "ERROR: Please supply credentials";

     

    else

     

    return "USER: " + sHeader.Username;

     

     

     

    }

     
    然后,客户端在调用要求标头的方法之前,直接在代理类上设置标头,如下面的示例所示:

    HeaderService h = new HeaderService();

     

    AuthHeader myHeader = new AuthHeader();

     

    myHeader.Username = "username";

     

    myHeader.Password = "password";

     

    h.AuthHeader = myHeader;

     

    String result = h.SecureMethod();

     
    3.2 .Net Remoting的安全认证方式
     
    CallContext提供与执行代码路径一起传送的属性集,CallContext是类似于方法调用的线程本地存储的专用集合对象,并提供对每个逻辑执行线程都唯一的数据槽。数据槽不在其他逻辑线程上的调用上下文之间共享。当 CallContext 沿执行代码路径往返传播并且由该路径中的各个对象检查时,可将对象添加到其中。当对另一个 AppDomain 中的对象进行远程方法调用时,CallContext 类将生成一个与该远程调用一起传播的 LogicalCallContext 实例。只有公开 ILogicalThreadAffinative 接口并存储在 CallContext 中的对象被在 LogicalCallContext 中传播到 AppDomain 外部。不支持此接口的对象不在 LogicalCallContext 实例中与远程方法调用一起传输。
    CallContext.SetData方法存储给定对象并将其与指定名称关联,CallContext.GetData方法从 CallContext 中检索具有指定名称的对象。
    下面的代码示例说明如何使用 SetData 方法将主体和标识对象传输到远程位置以进行标识。

    public class ClientClass {

     

       public static voidMain() {

     

          GenericIdentity ident = new GenericIdentity("Bob");

     

          GenericPrincipal prpal = new GenericPrincipal(ident,

     

                                              Newstring[] {"Level1"});

     

          LogicalCallContextData data =

     

     new LogicalCallContextData(prpal);

     

          //Enter data into the CallContext

     

          CallContext.SetData("test data", data);

     

     

     

         

     

          Console.WriteLine(data.numOfAccesses);

     

          ChannelServices.RegisterChannel(new TcpChannel());

     

          RemotingConfiguration.RegisterActivatedClientType(

     

    typeof(HelloServiceClass), "tcp://localhost:8082");

     

          HelloServiceClass service = new HelloServiceClass();

     

          if(service == null) {

     

              Console.WriteLine("Could not locate server.");

     

              return;

     

          }

     

     

     

          // call remote method

     

          Console.WriteLine();

     

          Console.WriteLine("Calling remote object");

     

          Console.WriteLine(service.HelloMethod("Caveman"));

     

          Console.WriteLine(service.HelloMethod("Spaceman"));

     

          Console.WriteLine(service.HelloMethod("Bob"));

     

          Console.WriteLine("Finished remote object call");

     

          Console.WriteLine();

     

     

     

          //Extract the returned data from the call context

     

          LogicalCallContextData returnedData =

     

             (LogicalCallContextData)CallContext.GetData("test data");

     

     

     

          Console.WriteLine(data.numOfAccesses);

     

          Console.WriteLine(returnedData.numOfAccesses);

     

       }

     

    }

     
    下面的代码示例说明如何使用 GetData 方法将主体和标识对象传输到远程位置以进行标识。

    using System;

     

    using System.Text;

     

    using System.Runtime.Remoting.Messaging;

     

    using System.Security.Principal;

     

     

     

    public class HelloServiceClass : MarshalByRefObject {

     

       static int n_instances;

     

       int instanceNum;

     

     

     

       public HelloServiceClass() {

     

          n_instances++;

     

          instanceNum = n_instances;

     

          Console.WriteLine(this.GetType().Name + " has been created.

     

                 Instance # = {0}", instanceNum);

     

       }

     

     

     

      ~HelloServiceClass() {

     

          Console.WriteLine("Destroyed instance {0} of

     

    HelloServiceClass.", instanceNum);     

     

       }

     

     

     

       public String HelloMethod(String name) {

     

     

     

          //Extract the call context data

     

          LogicalCallContextData data =

     

              (LogicalCallContextData)CallContext.GetData("test data");     

     

          IPrincipal myPrincipal = data.Principal;

     

         

     

          //Check the user identity

     

          if(myPrincipal.Identity.Name == "Bob") {

     

             Console.WriteLine("/nHello {0}, you are identified!",

     

    myPrincipal.Identity.Name);

     

             Console.WriteLine(data.numOfAccesses);

     

          }

     

          else {

     

             Console.WriteLine("Go away! You are not identified!");

     

             return String.Empty;

     

          }

     

     

     

            // calculate and return result to client   

     

          return "Hi there " + name + ".";

     

       }

     

    }

     
    4 详细代码设计
     
    4.1 WebService代码设计
    WebService端代码主要进行对数据库的操作,建立起Client操作数据库所需要的方法,供Client的端调用。

    1)class UserInfoMng() 用户信息管理类,其中包括方法:

     

    l         CreateUserInfo(string UserName string UserPwd) 建立用户信息,调用存储过程CreateUserInfo(@UserName,@UserPwd)

     

    l         ModifyUserInfo(string UserName string UserPwd) 修改用户信息,调用存储过程ModifyUserInfo(@UserName,@UserPwd)

     

    l         DeleteUserInfo() 删除用户信息,调用存储过程DeleteUserInfo

     

    (@UserID)

     

    2)class UserAuthentication() 用户认证类,用来实现用户角色、权限的设置,包括方法:

     

    l         CreatePermissionInfo(string PermissionName string Permissi-

     

    -onNote) 建立权限信息,调用存储过程CreatePermissionInfo

     

    (@PermissionName,@PermissionNote)

     

    l         CreateRoleInfo(string RoleName string RoleNote) 建立角色信息,调用存储过程CreateRoleInfo(@RoleName,@RoleNote)

     

    l         DeleteRoleInfo() 删除角色信息,调用存储过程DeleteRoleInfo

     

    (@RoleID)

     

    l         GrantUserRole(string UserID string RoleID string UserRoleNote) 授予用户角色,调用存储过程GrantUserRole(@UserID,@RoleID,

     

    @UserRoleNote)

     

    l         DeleteUserRole() 删除用户角色,调用存储过程DeleteUserRole

     

    (@UserRoleID)

     

    l         GrantRolePermission(string RoleID string PermissionID string RolePermissionNote) 授予角色权限,调用存储过程GrantRolePermission(@RoleID,@PermissionID,@RolePermissionNote)

     

    l         DeleteRolePermission() 删除授予的角色权限,调用存储过程

     

    DeleteRolePermission(@RolePermissionID)

     
    4.2 用户认证代码设计(Client端)
    Client端调用WebService方法来进行数据库访问,Client端代码设计主要实现界面的功能,包括:权限设置、用户管理、用户授权管理和用户认证管理

    1)权限设置

     

    class PermissionInfoMng() 用户权限信息管理类,包括方法:

     

    l         CreatePermissionInfo() 建立权限信息

     

    2)用户管理

     

    class UserInfoMng() 用户信息管理类,包括方法:

     

    l         CreateUserInfo() 建立用户信息

     

    l         ModifyUserInfo() 修改用户信息

     

    l         DeleteUserInfo() 删除用户信息

     

    3)用户授权管理

     

    class RoleInfoMng() 角色信息管理类,包括方法:

     

    l         CreateRoleInfo() 建立角色信息

     

    l         DeleteRoleInfo() 删除角色信息

     

    class UserRoleMng() 用户角色管理类,包括方法:

     

    l         GrantUserRole() 授予用户角色

     

    l         DeleteUserRole() 删除用户角色

     

    class RolePermissionMng() 角色权限管理类,包括方法

     

    l         GrantRolePermission() 授予角色权限

     

    l         DeleteRolePermission() 删除角色权限

     

    4)用户认证管理

     

    class Authentication() 用户认证类,包括方法:

     

    l         Login(string UserName string UserPwd) 用户登陆认证,用户认证通过分配给用户一个TicketID,否则TicketID则为null

     

    l         Logout() 用户正常退出

     
    l         ExceptionLogout() 用户异常退出
     
     
     
    展开全文
  • 任何一个系统中,都离不开权限的设计权限设计 = 功能权限 + 数据权限+字段权限【功能权限】:能做什么的问题。如查询、增删改信息【数据权限】:能看到哪些数据的问题。如查看本人、部门团队、区域或者整个公司、...

            任何一个系统中,都离不开权限的设计

    权限设计 = 功能权限 + 数据权限+字段权限

    【功能权限】:能做什么的问题。如查询、增删改信息【数据权限】:能看到哪些数据的问题。如查看本人、部门团队、区域或者整个公司、甚至整个系统的数据【字段权限】:能看到哪些信息的问题。如联系人姓名,但是不能查看到联系人地址、联系人电话这样的

    • 1.功能权限设计

            常常是基于RBAC(Role-Based Access Control)的一套设计方案

    • 2.数据权限设计

    • 2.1数据权限设计分析

            根据不同的业务场景,则权限却不尽相同,应该根据具体的场景巧妙设计;且必须在项目开始时进行设计,不像功能权限一样,在项目结束的时候在追加。数据权限做不到组件级别,必须在项目设计阶段就已经规划好。之前看网上相同有人想基于SPRING切面的原理去实现数据权限,这样就能够做到了低侵入、低耦合,想法非常好。但是现实非常骨感,这样做使整个应用系统效率大减折扣,相同对数据权限的控制策略也非常不灵活

    • 2.2SQL语句可扩展,数据权限设计分析

            数据权限往往作为功能权限的高级行为。能够从数据对象的幅度方面进行控制。比方用户仅仅能看自己的订单、普通会员看不到某数据对象的高级属性(字段)等等。颗粒度这么细的情况下对结果集处理显然是不可能了,这时仅仅能介入到SQL语句中,此时又不想在开发阶段让开发者过多的考虑数据权限的问题,这个时候就需要将sql 和数据权限策略分开。再调用接口的时候,进行数据权限接口的拼接。这样也算做到的代码的低侵入。

            数据权限模块的核心之中的一个就有SQL语句的高效解析处理,SQL处理指依据当前登录人信息及数据权限策略生成一个带有数据权限处理结果的SQL语句。所以这里对SQL语句的解析处理必需要求精确、准确。在开发阶段由开发者把SQL写入到配置文件里,在执行阶段由数据权限取得该SQL进行分析处理(加上数据权限),这样就完毕了SQL的组装处理。

    • 2.3方案

    • 2.3.1 方案一:按照岗位体系建立数据权限

    把权限赋予岗位,再把员工(用户)放在岗位上,从而间接把权限赋予用户。

            有的企业的数据权限很简单,就是普通员工只能看到自己的数据,部门负责人可以看到本部门的数据,高层管理可以看到所有下级部门的数据。这样可以把这套规则直接写死在系统里面,然后根据员工的任职岗位和部门去读取对应的数据范围即可。

    e1871a0cf2ceee954c329e03ff9324f8.png

    此方案的典型适用场景就是销售管理系统、客户关系管理系统(CRM)

    特点:数据权限的划分严格按照员工岗位体系划分

    优点:设置简单,只需要录入需要限制的单据,选择是按照部门或者按照下属来限制即可。

    缺点:需要维护一套岗位体系;不够灵活,无法查看跨部门的数据、上级领导的数据等

    也就是说,使用岗位体系数据权限只有两种结果,要么受岗位体系限制,要么没有限制(能看到所有数据), 其他需要限制但不是按照岗位体系限制的需求,则无法满足

    比如有些集团中心的财务、人事等岗位,需要看到整个集团的数据,但是他们又不是集团领导,其他人也不是他们的下属,这种情况岗位体系数据权限是满足不了的

    • 2.3.2 方案二:针对角色设置数据权限

    把权限赋予角色,角色叠加到用户上,从而间接把权限赋予用户。

    角色和岗位相比,有两个好处:1、岗位是在企业组织架构里面设立的,不能随意修改,但是角色是可以灵活设置的,比如可以设置一个“华南大区报销负责人”的角色,但是这个岗位在企业组织架构中不存在,所以不能设立这样一个岗位。2、角色可以多个叠加,比如张三又负责华南大区的费用报销,又负责华东大区的费用报销,就可以把“华南大区报销负责人”和“华东大区报销负责人”两个角色都赋予张三。但是岗位上张三是一个“报销专员”,并没有身兼多职。

    所以,角色比岗位要灵活很多。

    将单据中的每一个字段都作为一个数据权限对象,然后对这些字段设置比较条件,这些比较条件组合起来就形成一个针对该单据的数据规则。每一个数据规则有一个名称。

    比如,我们可以设置一个数据规则,条件是:客户所在地区等于A,并且,客户状态为待续签。那么这条数据规则就可以看到A地区待续签的客户,我们可以把它命名为“A地区待续签”。

    所以,数据规则其实是某张单据的一个数据范围,也就是某部分的数据。

    abaf87a0b1040983e89d8934013d3a85.png

    比较条件可以设置变量,比如客户的业务员为“当前用户对应的业务员”,更灵活更方便维护。

    设置好数据规则之后,我们把这个数据规则跟角色关联起来,就可以限制该角色能看到的数据范围了。

    fb9bbe59239a34168a38f18ad66e32a0.png

    如果不设置数据权限,则默认能看到所有数据。

    如果有多个角色赋予同一个用户,且不同角色的数据权限不同,则取范围的并集。

    此方案完美解决了方案一的问题,可以通过设置角色的权限来灵活地控制每一个用户的权限,满足很多特殊化的场景。

    缺点:1、需要维护用户的角色;2、数据规则虽然可以用变量,如果是多层的计算逻辑,则无法满足。

    • 2.3.3 方案三:岗位数据权限和角色数据权限的结合

    企业的数据权限需求,无非就两种,有些数据是基于岗位体系划分数据权限的,有些数据是需要灵活设置的。所以我们把方案一和方案二结合起来,就形成了适用性更高的方案三。

    此方案中,可以对角色设置岗位体系数据权限,同时还可以对角色设置其他的数据规则。也就是说,岗位体系数据权限和数据规则权限可以灵活切换、叠加来设置。

    有的人可以只按照岗位体系数据权限来限制,有的人可以只按照数据规则来限制;有的人还可以又有岗位体系数据权限,又有数据规则权限。

    如果同一角色同一单据,又设置了岗位体系数据权限,又设置了数据规则权限,则取两者的交集。

    举例:

    企业内所有员工都要使用费用报销模块,要求普通员工只能看到自己的数据,领导可以看到直属下级的数据。同时集团的财务张三负责华南和华东的费用报销,李四负责华北和华中的费用报销。

    此时可以设置三个角色:

    • 角色“岗位费用报销”,设置岗位体系数据权限,选择直接下属,并把角色赋予除张三和李四外的所有用户。则这些用户可以看到自己的数据及自己直接下属的数据。(普通员工没有下属,只能看到自己的数据)。

    • 角色 “华南和华东的报销专员”,设置了数据规则为“报销部门为华南 或 报销部门为华东”,该角色赋予张三。

    • 角色 “华北和华中的报销专员”,设置了数据规则为“报销部门为华北 或 报销部门为华中”,该角色赋予李四。

    普通员工和领导有岗位体系数据权限,财务张三和李四有数据规则数据权限。

    76b899c4a9851b36af1b94bd789bb772.png

    22a7c315ceab5f2faade932d043a0a8a.png

    方案三综合了以上两者的优点,更加灵活便捷。很少企业是完全按照岗位体系来划分数据权限的,也很少企业所有的数据权限都可以用数据规则来限制,大多数是两种需求都有的情况。所以方案三的适用性更好,更适用于全员应用的系统。

    方案都有好坏,主要是看不同的系统及企业权限管理需求。核心方案是:数据范围划分清晰、准确,设置灵活、维护成本低。

    数据是一个企业最重要的资产。很多企业之间的竞争,其实也是数据之争,资源之争。数据权限,就如同为数据筑起的一座座城墙,清晰地划分了用户能看到的数据范围,为数据提供安全保障。

    展开全文
  • 权限设计教程

    2019-06-18 15:50:17
    https://www.jianshu.com/p/4ca68900f4d6 (2、用户权限管理,数据库表设计) https://blog.csdn.net/painsonline/article/details/7183613/ (RBAC权限管理, role-base-access-controller) qyerp设计权限设计: ...
    1. https://www.jianshu.com/p/4ca68900f4d6 (2、用户权限管理,数据库表设计)
    2. https://blog.csdn.net/painsonline/article/details/7183613/ (RBAC权限管理, role-base-access-controller)

    qyerp设计权限设计: (把file, menu, page_ele, func_oper都加到permission中去, 用一个type来做区分, 写sql会轻松很多)
    把file, menu, page_ele, func_oper都加到permission中去, 用一个type来做区分, 写sql会轻松很多

    二. RPAC
    1. https://www.jianshu.com/p/9d00105b5d0d?utm_source=oschina-app (SaaS后台经验分享:如何设计权限管理)
    2. 117赞 https://www.jianshu.com/p/be7d264fe1b3 (大型系统后台设计——权限篇)
    展开全文
  • 权限设计=功能权限+数据权限 权限管理 Authority Management 目前主要是通过用户、角色、资源三方面来进行权限的分配。 具体来说,就是赋予用户某个角色,角色能访问及操作不同范围的资源。 通过建立角色系统,将...
  • 一、前言几乎在任何一个系统中,都离不开权限的设计,权限设计 = 功能权限 + 数据权限,而功能权限,在业界常常是基于RBAC(Role-Based Access Control)的一套方案。而数据权限,则根据不同的业务场景,则权限却不尽...
  • 权限设计模式

    2019-07-08 16:00:00
    权限设计模式 自主权限访问控 DAC的概念 DAC: Discretionry Access Control DAC权限模式下系统会自动识别用户,然后根据被操作对象(Subject)的权限控制列表ACL(Access Control List)或者权限控制矩阵(ACM:Access ...
  • 数据权限设计研究-行数据权限

    万次阅读 2019-01-17 19:22:56
    数据权限设计研究-行数据权限关于权限设计功能权限数据权限前提数据分类几种场景设计方案与思路映射表提供过滤sql的方法测试实际应用查询新增修改删除修改数据的私有,公开,部门属性私有改为部门私有改为公开部门改...
  • 角色权限设计

    千次阅读 2019-02-20 15:03:21
    角色权限设计一 ·RBAC模型1.基本的RBAC模型2.引入用户组概念的RBAC模型3. 角色继承的RBAC模型4. 限制的RBAC模型二·权限的拆分与设计三·需要注意的Tips 一 ·RBAC模型 1.基本的RBAC模型 RBAC(Role-Base Access ...
  • java权限管理与用户角色权限设计

    万次阅读 多人点赞 2018-06-16 00:14:28
    java权限管理与用户角色权限设计2016年10月29日 19:24:41阅读数:12545实现业务系统中的用户权限管理 B/S系统中的权限比C/S中的更显的重要,C/S系统因为具有特殊的客户端,所以访问用户的权限检测可以通过客户端...
  • RBAC权限设计

    千次阅读 2016-03-11 11:13:19
    ...RBAC权限设计   (2012-03-04 19:05:22) 转载▼ 标签:  rbac权限设计   权限设计   权限   角色   数据设计   it   分类: IT小知识
  • 分享一个大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!... saas平台由于其本身“按需购买”...作为一个B端平台型产品,系统的权限设计是其中一个非常重要的组成部...
  • 基于角色的权限设计
  • ofbiz 权限设计详解

    2017-08-26 12:19:39
    ofbiz 权限设计
  • 数据权限设计——基于EntityFramework的数据权限设计方案:一种设计思路 正文 前言:“我们有一个订单列表,希望能够根据当前登陆的不同用户看到不同类型的订单数据”、“我们希望不同的用户能看到不同时间段...
  • 权限设计-系统登录用户权限设计

    万次阅读 多人点赞 2018-01-08 09:56:06
    假设需要为公司设计一个人员管理系统,并为各级领导及全体员工分配系统登录账号。有如下几个要求: 1. 权限等级不同:公司领导登录后可查看所有员工信息,部门领导登录后只可查看本部门员工的信息,员工登录后只可...
  • 用户权限设计方案

    千次下载 热门讨论 2013-05-28 16:03:42
    为了设计一套具有较强可扩展性的用户认证管理,需要建立用户、角色和权限等数据库表,并且建立之间的关系,提供的一种设计方案
  • java角色权限设计

    2018-12-19 13:48:14
    java用户角色权限设计   实现业务系统中的用户权限管理  B/S系统中的权限比C/S中的更显的重要,C/S系统因为具有特殊的客户端,所以访问用户的权限检测可以通过客户端实现或通过客户端+服务器检测实现,而B/S中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 28,789
精华内容 11,515
关键字:

权限设计