凡是多用户的应用系统往往都有权限访问控制的要求。权限访问控制的本质是”Who“对"which"进行"what"操作的布尔表达式。如果你通过独自深刻的思索或者参考别人的文章,充分而又深刻的认识到这一点,那么,恭喜你,你已经把握到了问题的本质,对权限访问控制的认识已经入门了,但也仅仅是入门了而已。当你基于这个本质,开始设计现实中的权限访问控制模块时,你会发现,果然,理想很美好,现实太骨感,你成功地陷入了一个泥潭,但值得高兴的是,泥潭中已经有了许多同志,吾道不孤呀。
设计是针对过去、现在和未来的一种思考,过去、现在容易把握,未来却难以掌控。我们设计出来的模型应该可以应付一定范围内的场景变化。即任它场景如何变化,我们的设计模型却巍然不动,颇有点”他强由他强,明月照大江;他横由他横,清风拂山岗“的境界。针对权限访问控制的设计模型却一次次地在现实场景中被击垮,让我们来重走这一历程。
开始,你可能想象设计一个界面,让系统管理员显示指定”Who“对"which"进行"what"操作的许可(这里的”who"代表着角色或者岗位,否则你会面临着某某离职、某某又上岗,需要重新授权等麻烦事)。是的,你已经成功地解决了权限控制的问题,解决的方式是你将问题抛给了系统管理员。想象一个企业级的文档系统,1000个用户、10万个文件、5种功能操作(文档发现、文档属性读、文档属性写、文档内容读、文档内容写),那么有多少个显示的授权要求呢?5亿个授权,这是人能做的事情吗?只有神了吧。
模型击垮了,于是通过我们认真思索、思索、再思索,终于发现,原来"which"具有层次化组织属性,当我们显示授权某个用户对公司文档的某种操作许可时,往往也隐式地指定了该用户对公司下属部门文档同样的操作许可。通过“which”的层次化组织属性和隐式的继承属性,我们成功地解决了授权量膨胀问题。在最极端的情况下,我们只需显示指定每个用户对公司文档的显示授权即可,此时显示授权量只有5000个了,虽然还是有点多,但基本上属于人级的操作范围了。但再想想,真的吗?真的是只要能进入大门,就可以到处溜达,到处看看了吗?如果这样,那我们是不是可以进入财务室,打开保险柜,看看里面有多少现款,想想都是多么激动人心的事啊。哦,原来资源还有自身的安全属性,不是隐式继承单独可以解决的,你可以到阅览室看看,但财务室依然是非请勿入的。
于是,我们的权限设计引入了文档本身的安全属性,文档的权限控制由附加在文档上的显示授权信息、文档所在目录路径的隐式授权继承信息、文档自身的安全属性信息三方依次作用的共同结果。附加在文档上的显示授权信息权限控制级别最高。当显示授权信息存在时,即按照该显示授权信息控制文档的访问权限;当显示授权信息不存在时,则由后两者共同作用来决定文档的访问属性,只有文档所在目录路径的隐式授权许可存在,且当文档本身的安全属性为public时才可以访问该文档。这样,财务室的文档缺省属性是Private,而其他一般部门的文档属性缺省为public。具有隐式授权信息的用户可以访问其它部门的文档,而不能访问财务室的文档。
然而,还有两个需要考虑的问题,一个是本部门人员对本部门文档的隐式访问问题,另一个是财务总监、公司经理等对部门文档的隐式访问问题。前一个问题我们可以引入文档自身的"Protected"安全属性,即同部门的用户可以隐式访问本部门的具有"Public"或"Protected"安全属性的文档,其他部门的用户仅能隐式访问本部门的具有"Public"安全属性的文档。后一个问题我们通过引入文档自身的"Friend"安全属性予以解决,即授权财务总监对财务室的文档为"Friend",这样财务总监可以查看财务室的所有非"Private"文档。
问题好像都解决了,现在让我们看看文档搜索,假如用户根据一定的关键字搜索文档,此时需要针对10万文档中的每个文档,分别进行显示、隐式的安全判断,处理工程量非常大,性能不可接受。最终我们发现,即便使用了文档的隐式继承授权信息以及文档自身的安全属性,需要处理的授权许可信息依然太大。于是我们反思,哦,是我们对文档系统权限控制的which控制力度太细,如果你想针对撒哈拉沙漠的每一粒沙都带上一把锁,锁的成本就远超沙的成本。退一步,我们仅对文档目录进行权限控制。