1+1=2,0+0=0

日月累积
posts - 7, comments - 50, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

最近项目的项目很奇怪,一个大项目(系统)里包含了很多小的子系统,而这些子系统中都有权限控制的部分,这件事情挺让我头痛的,记得一年前在沈阳,我曾经有一段时间也因因这个问题而疲于奔命,为什么说疲于奔命呢?由于当时项目进度不允许,导致最终系统权限模块草草了事,每个模块都是由读权限字符串来控制用户ACL,当用户无法访问时,提示权限不够。这么做对用户是很不负责任的,既然让用户看到了操作的方式和界面,为什么又告诉用户没有权限呢?我开始怀疑我们是否应该在底层就封杀用户的访问权限。

现在项目开展起来了,虽然目前我已经有了对权限控制的一套方案,并且实施成了我的可重用框架代码,虽然目前的权限也是基于众星捧月的AOP思想,但我至今对权限设计仍有两个疑惑:

疑惑一:很多同行提出方案,想要在底层就截取用户权限,控制用户对方法或者类的访问。这样做的好处在于可以将系统功能与业务逻辑松散耦合,并且实现简单,结构清晰,三两个advisor、filter,或者acegi就能搞定,但在web程序中体现出了他的劣势,当我们将用户的访问拒绝在业务逻辑之外的时候,我们此时是否应该抛出异常提示用户?一旦提示用户没有相应的权限,我认为对于用户来说,这就不是一个perfect practice。由此得出,我们根本就不应该让用户做此次操作,而控制用户操作的源头就是界面,也就是说,在界面上我们就应该对用户的权限元素(如添加按钮、功能菜单等)进行控制。此时,一对矛盾出现了,要控制界面上形形色色的元素只有两种办法,一,将权限与你的界面结合起来设计,这将违背AOP的思想,也使得系统控制模块的重用性大大下降,二,我们借鉴primeton的想法,将权限控制的理念抽取出来,单独做成一套权限系统,解决你所有的需要权限控制的系统需求,这样也有令人头痛的问题,你的所有想用它来控制权限的系统,必须界面上统一风格。或许这样的方式对商业web系统是合适的,毕竟需要你大刀阔斧个性化的地方不多,但我们却很难保证在未来几年内商业web系统的风格不改变。再者,开发这么一个系统也不是一蹴而就的事,在这个问题上一直让我困惑不已。


疑惑二:大多应用的权限判定是基于权限字符串的,但存储在数据库中的权限字符串能够判定的权限并不多,在我们这次项目中,我引用了基于二进制的8421权限判定法则,我深深的感觉到权限字符串的弱势,这使我想起了中国古老一套数学理论-“盈不足术”,超递增序列的魅力在我眼前滑过,

首先我来解释一下盈余不足理论:有十只盒子,第一个盒子里放一个盘子,第二个盒子里放两只,第三个盒子里放四只,第四个盒子里放八只……第九个盒子里放256只,第十个盒子放512只,即第N只箱子里放2^(N-1)只盘子,一共1023只。那么命题如下:在1023这个数字之内,任何一个数目都可以由这十只盒子里的几只组合相加而成。那么1、2、4、8、16、32、64、128、256、512这个序列为什么有这么个魔力?这个数列的特点:1、每项是后一项的二倍,2、每项都比前面所有项的和大,而且大1。这个1就是关键,就因为这个1,它才可以按1递增,拼出总和之内任意一个整数。这个序列叫做超递增序列,它是解决背包问题的基础。3、拼出总和之内任意一个整数可以由这个序列中的一些数构成,且构成方法唯一,据说是密码学中的NP定理。譬如说这个数列总合中20这个数,只能由16+4一种方法构成,由此延伸出来,如果综合中这个数据代表一个权值,我们可以解出它的所有构成参数(操作),如20这个数据,我们可以挨个和序列中每一项按位与,得出来如果不等于0,就说明他是由这个数构成的。

保存权值到int还是varchar对于我们来说是个问题,当然,保存字符串的好处是运算压力小。我们可能听过一个故事,就是把这个超递增序列延伸到第64项,就是那个术士和皇帝在国际象棋棋盘上要米粒的传说。64项的和是一个天文数字!但计算机本身就是一个只认识二进制的机器!很多程序员整天只关心架构,甚至不知道或者不关心位操作是什么玩意,当然我们有朋友担心数据库的int不够长,那么既然可以保存一个只有0、1组成的varchar字符串,为什么不能保存一个十六进制的字符串,有人规定varchar只能保存01吗?十六进制串的长度正好是二进制的四分之一。

由此我们可以无限制的扩展权值操作。

在最近的项目里,我对权限的控制分成两个部分,第一就是用户体验上,我设置了一个权限标签,从数据库中抽取权限信息,然后做到标签里,也凑或算成是界面AOP了,第二就是底层的拦截,用了Spring 的AOP,为的是防止权限冲突,双管齐下。暂时解决权限所需,另外在算法上我用了16进制的权限判别代码,虽然配置较麻烦,写完代码还要写文档说明,不过也解决了权限繁杂又多的问题,暂时就这样了,嘿嘿,以后有空再研究。


评论

# re: web开发中的权限设计拙见一二  回复  更多评论   

2007-01-02 13:39 by ant
如能结合些代码谈谈,更佳。好文,关注!

# re: web开发中的权限设计拙见一二  回复  更多评论   

2007-01-02 14:29 by BeanSoft
赞一个!

# re: web开发中的权限设计拙见一二  回复  更多评论   

2007-01-02 14:31 by 绿色使者
其实上面用二进制一下子就解释清楚了,1,2,4,8就是二进制的基,每一个十进制数当然可以用唯一的这些二进制基表示出来啦

# re: web开发中的权限设计拙见一二  回复  更多评论   

2007-01-02 21:55 by jerson[匿名]
字也太小了吧

# re: web开发中的权限设计拙见一二  回复  更多评论   

2007-01-02 22:22 by 海思
是否可以把16进制的权限判别代码的相关代码和文档发份给我看看呢?
我最近也在研究权限部分,由于对这块不熟,比较头痛,谢谢
如果可以的话麻烦发份到我邮箱
chmk35@163.com
谢谢

# re: web开发中的权限设计拙见一二(1)  回复  更多评论   

2007-01-02 22:44 by 江上一叶舟
首先对大家的关注表示感谢^_^
另外由于我不会在评论信息中加载代码,所以我将本文中的标题后面加上了(1),我将在我随后的几篇随笔中分别谈一下我的权限分配的相关数据库设计、数据库与权限关联配置、界面权限控制和底层拦截机制,小文确是抛砖引玉,谢谢关注~~:)

# re: web开发中的权限设计拙见一二(1)  回复  更多评论   

2007-01-02 23:04 by errorfun[匿名]
嗯,不错,和我做的第一个项目时的想法一样,权限系统也用了这个8421的方式实现,没有权限的人就看不到菜单,看不到操作。这样处理也是我觉得比较方便的做法了。不过后来是用了四个字段分别表示增删改查这四个方法,1表示有权限,0表示没权限。
当时也是想了很多方案后才决定了,因为对于数据操作不外四种方式:查看,增加,修改,删除。查询,分析,报表之类的都可归入查看之中。我是用数据库保存权限的,因为觉得但用户很多权限也很多时,数据库的读取比XML快上许多。只是在第一次读取相关操作时,加载所需的权限的数据,加载完后以后访问就不用再加载。而XML保存一般都在登录时加载了所有权限,但XML在大量数据时读取速度确实不感冒。

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-02 23:46 by 江上一叶舟
呵呵,我目前所用到的权限种类繁多,所以权值也很多,权值基本的计算公式我就用了2的n-1次方,这样权值可以无限扩展,无论是增、删、改、查、报表、上传、下载,我都会分配一个权值,如果一个角色拥有多个权限,则这个角色的权值为他所拥有的所有权限的权值的和,我将权值的和以16进制的形式记录到库中,基本上来说一个用户对一个资源在数据库中只有一条权限记录

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-02 23:51 by 江上一叶舟
另外对于权限的记录来说,用数据还是xml文件来记录我认为主要不在读取速度上来区分,因为大多角色权限信息我会放入内存中,所以xml还是数据库来记载对我来说无所谓,但有一点区别是致命的,就是当你修改权限信息时,你需要修改相应的纪录,很明显修改数据库记录要比修改xml文件来的方便,io操作还是挺让人~~~嘿嘿

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-03 12:08 by errorfun
怎么说呢,其实在以前我也考虑过你这个无限扩展的问题,但仔细一想,权限不存在无限扩展,权限基本的都是增删改查,因为它们都是对数据库的操作,
比如你说的上传功能,它只不过是对上传的内容进行增加操作,再如下载,也不过就是对上传内容的查看操作,你有查看权限了,自然有下载功能,有增加权限了,自然有上传功能。
再如报表,你不过是对报表这些内容的查看权限,所以不存在扩展性问题。
不要被扩展性所迷惑,我开始设计权限时也一度被8421的可扩展性所迷惑,但最后想仔细,其实也就只有四个操作而已,放成四个字段,比8421的方式容易修改,也容易知道有哪些权限,不用再进行计算。就像你说你用16进制存权限吧,如果我1表示查看,2表示增加,4表示修改,8表示删除,那如果我进行增加操作,那你就得判断我的权值是否是2,3,6,7,10,11,14,15,这其实是增加的复杂性,权限系统本身就很复杂了,如果在权值上面还进行人为的复杂化,而仅仅为的是不存在的扩展性,那我觉得是得不尝失的。
如果是在小数据量时,XML文件方式不是不错的,可惜权限本身就是大数据量的,针对这个问题其实我也想过一个解决方案:把每个人的权限放到一个XML文件中,因为针对个人的权限来说,相对还不算太大,然后用一个主XML存放相关文件的信息,而每个信息对应的就是这个人员的KEY,能唯一查找到对应的XML。这在某程度上应该可以解决XML加载的速度问题,但觉得不安全,因为XML文件很难对其读写进行权限控制,被人不小心删除了或修改了,那也是一件麻烦的事,所以最终也没用XML文件实现。

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-03 12:23 by errorfun
PS:上面说的对权值的判断,可以对16进制进行toBinaryString()进行判断第N位是否为1,但如果在权限设置页面时,用STRUTS标签是很难进行这样的判断,一种方式是在页面用嵌套JAVA的方式进行处理判断,另一种方式是在数据读取后,在返回前进行遍历处理。第一种不用多说,现在还在页面嵌套JAVA的做法已经被人抛弃了,原因就不多说。第二种自然只是在效率上有所减少而已。取舍还是看你自己了

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-03 13:10 by 江上一叶舟
1,楼上的或许还是没有看懂我所说的权限设计,倘若你的‘增加权限’设置为1,而a这个角色当前所拥有的权值是30,那么只需要1&30进行二进制运算,不等于0,则说明有增加权限,没有你说的那么复杂。

2,另外你所说的在页面嵌入java代码我不知是从何判断,我是做好了一个现成的权限标签,包在你需要判断的页面元素之外,如你可以在页面上这么写:
<privilege scope='session' operation='create' beanName='userinfo'>
<input type="button" value="添加">
</privilege>
这样系统会自动为你判断当前用户是否具有添加权限,从而为你设置页面上是否显示添加按钮

3,权限是人定的,我可以把对这个资源的增加定为一种权限,上传定位一种权限,客户可能要求此人只能上传不能增加(我说的上传是指以excel文档的形式上传上来,解析其中的数据并添加入数据库中),都是有可能的,可能你还是认为他们都属于添加操作,但用户就是要求你不能添加,只能上传,只有它指定的人才能添加。另外我说的报表,不仅仅是察看,我们可以定义一种形式的pdf报表,将数据库中的数据导出到pdf,并形成饼图、曲线图等,这和查看可以说完全是两种不同的操作,所以权限是没有限制的,也就是说实际系统中对一个资源的权限可能最多也就10种撑死了,但我们需要做到的是:无论对这个资源的权限如何扩展,我们都可以应对,不是么

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-03 15:46 by errorfun
1、确实没想过这么处理,今天算是学到了。
2、是一个好办法。
3、如果是上传EXCEL的话,可以看成是对文件的添加操作,解析数据可以看成是对数据的添加操作,都是一样的,文件也不过是数据存储的一种方式,数据库未出现之前,数据就是以文件的形式保存的,难道数据库出现后,对文件的上传而不保存到数据库中就不能算是添加操作了?不要跟我说你只是让他上传,但上传后是不保存在服务器或数据库或其它的任何地方,而仅仅是能点上传按钮而已。
而报表形成饼图也是一种权限的话,可以把它设置成对饼图的查看操作,对曲线图的查看操作,导出到PDF,也不过就是对PDF的查看操作,不过,个人认为,即然你都可以看到源数据了,饼图,曲线图却不让人看,还让人家自己去画不成?

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-03 16:53 by 江上一叶舟
@errorfun
1,呵呵,上传文件仅仅是添加操作,我们只是获得request流,解析流中数据,并且添加入数据库,如果您硬要认为这个操作就是添加数据,我觉得也不无道理,但客户的需求是这样的:高级系统管理员角色可以一次性用excel导入一大批数据,普通的管理员不能进行这样的导入操作,只能逐条添加,于是乎,您认为的这两种“添加”操作在我们的系统中被看成是不同的两种权限。

2,您提到“即然你都可以看到源数据了,饼图,曲线图却不让人看,还让人家自己去画不成?”,您的这个想法无可厚非,但目前的需求是这样的:普通管理员只能看到数据,即查看源数据,而领导要求只对他开放数据汇总成图形的功能,也就是数据统计后的图形查看功能,领导不关心源数据,只关系数据的统计结果和比例

3,我觉得您的理解固然没错,但不同的客户的需求不同,您所说的内容是针对需求的理解问题:)

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-03 17:30 by 坏男孩

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-03 19:37 by errorfun
@江上一叶舟
1、对于所说的情况确实是存在,如果是我,我会将领导的那种一次性导入看成是另一个资源操作,而权限是对这个资源操作的设置,对普通管理员,则没有这个资源操作的权限,就像一个页有增加,删除,修改,查看,导入,上传,下载的功能一样,增删改查,我会看成是一个ACTION中的操作,导入看成是另一个ACTION中的操作,上传下载看成是第三个ACTION的操作。一个页面分离成三个ACTION的权限设置,就是这样而已,不是说硬要认为。数据的读取方法,过程,可以不必特别在意,抽象出来后都一样。“获得request流,解析流中数据,并且添加入数据库”不过就是获得数据,保存数据的过程,和页面填写数据,然后提交保存入数据库是相似的,不同的只是过程。

2、我说的问题之前也说了它的权限设置可以看成是“对饼图的查看操作,对曲线图的查看操作,导出到PDF,也不过就是对PDF的查看操作”,所以对于领导的要求也是能完成的,普通管理员只有查看数据的权限,领导有查看饼图的权限,查看曲线图的权限。

3、当然我说的也并非是针对某一需求的理解,而是将页面的操作进行抽象后的理解所说的。呵呵

权限有的是基于ACTION或URI,有的是基于资源的,可能你的是基于资源的,所以和我的想法并不是相同的。权限开得更清楚也不是没有好处,至少在设置权限时用户更加清楚它设置的权限对哪个操作有影响。
就像我一开始说的,这是我第一个项目时所想的权限系统,当时所想的也是要简化复杂的权限系统,而没有关注到用户设置权限时是否清楚的问题,时隔一年,现在的权限设已大不相同,操作的定义在于XML文件中,而非数据库或用权值表示,操作可以有十个或一百个,这都不影响,设置权限时读取的是XML文件中的信息,它显示用户可以设置哪些操作,操作对应的模块等等的信息。而设置后的相应信息同样保存进数据库,在用户登陆时再进行加载。数据库保存的就是XML文件中的模块或操作的ID,权限具有继承的能力,系统权限优于模块权限等等。这些都是根据市场和自己的理解变化而变化的。只是在看到你这篇文章后令我想起了自己设计的第一个权限系统而有感而发而已,不要见怪。

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2007-01-03 22:14 by 小贺
好文章! 学习了!!

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2008-02-28 12:22 by black
就是泛泛的说,又没有一个简单的例子,理论

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2009-03-26 23:40 by interdrp
权限->策略->用户 实例 www.interdrp.com 下载分销系统客户端,用系统提示的默认的帐套及用户名进入系统即可。
有什么好的想法也可以在 http://www.cnblogs.com/interdrp/ 提出,谢谢

# re: web开发中的权限设计拙见一二(1)----设计思路  回复  更多评论   

2011-08-10 10:58 by 1h
rtyrt

# re: web开发中的权限设计拙见一二(1)----设计思路[未登录]  回复  更多评论   

2011-08-10 11:00 by lh
哥们! 可以将代码和数据放在我邮箱吗。谢谢
76162111@qq.com

只有注册用户登录后才能发表评论。


网站导航: