十年磨一劍--從程序員到架構師

一个.net程序员,一个企业应用的开发者,喜欢系统架构,数据库,领域驱动,面向对象,表现层技术。关注重用的理论和实践。设计原则:简单,快速,适应变化能力强,表现层灵活多变...

博客园 首页 新随笔 联系 订阅 管理

  在看了自适应软件......我今天在做我們一個新的系統功能權限的時候,有一點新的想法,不知道是不是班門弄斧,歡迎扔扔雞蛋! 后﹐发现大家对于系统权限还是很关注﹐因此在继续我的安全模块设计之前﹐再对以系统功能作为权限管控的方法进而实现系统安全的完全脱耦方案进行说明。

我以一个实际的小型订单管理系统为例来实现这种权限设计方案﹐也欢迎大家能提出自己的权限设计方案来对比﹕

 某某公司在线订单管理系统的用户需求说明书﹕

1.      要求系统实现﹕下单﹐订单维护(包括修改和删除订单)﹐订单审核﹐收款﹐发货﹐各种单据的查询和报表功能。

2.      只有注册用户才可以下单

3.      用户可以修改和删除他自己的未审核订单

4.      管理员可以删除未审核的所有订单

5.      销售经理进行订单审核﹐但只可审核其所在区域的订单﹐管理员可以审核所有区域的订单

6.      财务部门可以进行订单收款确认动作

7.      仓库管理者在订单审核并且财务部门收款后发货

8.      注册用户可以打印他自己下的订单。

9.      销售经理可以打印其所在区域的订单﹐管理员可以打印所有区域的订单

10. 管理员,财务部门可以打印收款报表

11. 管理员,仓库管理者可以打印出库报表

 

对于这个系统﹐在需求分析后提取的系统功能有﹕

1﹕下单

2﹕订单维护(修改和删除自己的订单)

3﹕管理员订单删除

4﹕订单审核

5﹕收款

6﹕发货

7﹕用户订单报表

8﹕审核者订单报表

9﹕收款报表

10﹕出库报表

 

系统设计﹕

1:下单﹕用户登录-->用户挑选商品-->预览商品列表-->下单提交

2:订单维护﹕用户登录-->按用户ID抓取他的所有订单-->用户修改或删除未审核未收款的订单

3:管理员订单删除﹕用户登录-->抓取所有的未审核未收款的订单-->删除用户所选订单

4:订单审核﹕用户登录-->抓出其权限区域下的所有待审订单-->审核订单

5收款﹕用户登录-->输入收款订单号或其它查询条件查出订单-->填入相应订单的收款数据-->提交确认

6:发货﹕用户登录-->抓出所有已收款﹐已审核的订单-->填入相应订单的发货数据-->提交确认

7:用户订单报表﹕用户登录-->打印用户自己的订单数据

8:审核者订单报表﹕用户登录-->打印其权限区域下的所有订单数据

9﹕收款报表﹕用户登录-->打印收款报表

10﹕发货报表﹕用户登录-->打印所有发货报表

 

在系统的业务功能出来后﹐我的权限管控方案也相应的出来了﹕

.开发者按照我的系统设计﹐相应的开发出对应这些功能的程序﹐而完全不需考虑权限部分。

在这里一个系统功能并不一定表示一支程序﹐同一支程序里你完全可以实现2种或以上的功能。

如﹕程序员在接到订单维护和管理员订单删除这两个功能后﹐它决定只用一支程序OrderMaintain.aspx程序来实现﹕

但是他怎么区分是否该显示删除按钮﹐修改按钮﹐还是区分该传 user id抓订单数据还是抓所有数据?

我没有告诉开发者任何有关权限的信息﹐因此他完全可以以这种方式来区别。

If(Request.QueryString[“kind”] ==”1”)

        这是订单维护功能(所以按user id抓订单数据﹐并显示修改﹐删除按钮)

Else if(Request.QueryString[“kind”] == “2”)

        这是管理员订单删除功能(抓所有数据﹐并只显示删除按钮)

而无需书写这样的代码﹕

if (user.has(“订单维护”))

        抓自己的订单﹐并显示修改﹐删除按钮

Else (user.has(“管理员订单删除”))

        抓所有订单﹐并显示删除按钮﹐隐藏修改按钮

 上面方式有以下缺点﹕

1.权限判断has方法与业务系统紧耦合

2.我没有说这两种权限不能同时拥有﹐如果用户又有订单维护﹐又有管理员订单删除功能怎么办?

 其它诸如以角色判断更是不可取﹐将角色hardcode进业务代码中﹐万一用户的角色需要变更那你不是麻烦大了?

 

二.在系统开发完后﹐系统上线前﹐要求程序员将程序交给我﹐如﹕

下单:       order.aspx productlist.aspx

订单修改﹕ ordermaintain.aspx?kind=1 orderlist.aspx

管理员订单删除﹕ ordermaintain.aspx?kind=2

订单审核﹕    check.aspx orderlist.aspx

收款﹕    pay/*
等等

 

.分配权限(新增角色列表﹐分配角色权限﹐将用户对应到角色﹐也可以通过权限分配程序让用户自己维护这些数据)

群组                系统功能

普通用户        下单

普通用户        订单维护

管理员            管理员订单删除

区域经理        订单审核

管理员            订单审核

财务部门        收款

仓库管理者    发货

普通用户        用户订单报表

区域经理        审核者订单报表

管理员            审核者订单报表

财务部门        收款报表

管理员            收款报表

仓库管理者    出库报表

管理员            出库报表

(当然上面只是一种对应关系﹐具体数据架构怎么设计可以通过流行的01掩码来实现其判断和存储)

 

.Request时通过URL分析对应到的系统功能(可以有多个)﹐然后判断用户是否拥有任一对应到的功能﹐就让它过﹐否则就拒绝(具體實現可參考這個系列的前几篇以及后續)。

 

从上面可以看出﹐程序员在开发系统时是无需关注任何关于权限管控的非业务代码的﹐它们只需按照系统设计时的流程完成程序即可。而在开发时配置权限数据﹐运行时动态分配权限更是让系统可适应于任何的关于权限需求变更。

 

不知道有没有读者发现﹐订单审核时的权限是如何实现的?

数据权限的概念﹕

用户在需求中提出﹕在订单审核时﹐销售经理可以打印其所在区域的订单﹐管理员审核所有订单。

这种情况我们将其认定为数据权限。而数据权限归属于业务需求﹐对于业务需求我们认为其实现必须和业务代码在一起开发。

比如在这里﹐我们会在设计时

指定这个页面的初始化流程﹕抓出当前登录用户-->抓出当前登录用户的权限区域-->将权限区域数据代入抓出待审核订单。

指定用户单击审核按钮时的流程﹕找到当前选择的订单号-->调用审核方法进行审核-->显示审核结果

从这里我们可以看出﹕

1.            对于用户应该审核哪些订单数据﹐我们并没有依据其是管理员还是区域经理﹐而是将这种情况认定为数据权限﹐这在以后面对用户的这部分需求变更时可以无需任何系统更新动作。

àA区域经理在休假后﹐B区域经理代理其审核A区域的订单。

à由于某种原因﹐要求C区域经理和D区域经理共同审核C区域和D区域的订单。

àE区域经理升迁为副总后﹐审核E,F,G,H区域的订单。

à总经理要求﹐他自己可以在系统运行时﹐指定他的几位助手审核他指定的某些区域的数据

因此抽象出數據权限﹐并且将其归类到业务功能上﹐我们很容易就可以处理这些需求的变更

2.            通过系统的初始化流程可以看出﹕不会出现用户审核到他无权审核的订单这种情况﹐因为我们在程序开发时﹐就是抓的权限区域下的订单﹐因此用户只能审核其有权审核的订单

 

顺便再提一下﹕系统中出现的关于管理员”,”注册用户”,”普通用户”,”财务部门”,”仓库管理者等这些群组对象﹐不管在业务程序中还是在权限判断时﹐都不会出现任何关于这些的hardcode代码﹐他们只不过是用户对应权限的一种方式而已﹐不是权限系统所必须的

 

关于web应用程序安全方案的完整实现请继续关注这个系列

posted on 2006-12-29 12:23  Kevin Zou  阅读(3227)  评论(8编辑  收藏  举报