L型代码结构案例:Link访问权限(上)
这是松结对编程的第20篇(专栏目录)。
本文探讨Link访问权限的最佳实现方法,力求外观干净且封装良好。
这些代码将位于L型代码结构(参见松结对编程系列中的定义)的下层,调用者无需理解其原理。
顺便说一下,我们做的是管理信息系统,和互联网社区软件的一个区别是很多链接都是需要特定权限才能访问的,有些权限也不是非常直观能猜到应该具备何种条件才能访问,另外一些权限还会经常改动。因此一个容易使用、容易维护、不容易出错的权限机制尤为重要。
无权访问时该显示什么在说实现方法之前,先说说如果链接访问条件不满足,应该显示什么。
实践发现显示文字不好,因为文字(这里应该是一段解释为何不能访问的文字)肯定比链接长,显示空间不好。
什么都不显示如何?也不太好,用户可能会误以为没有这样一个功能,或链接不在这个页面上而去其他页面寻找。
最后现在是显示一个灰色的链接,悬停时解释需要什么条件才能访问这个链接(这样用户如果想操作它但却没有权限,就会知道该怎么办)。
显示方法方法1:散装代码一般而言,如果要限制一个Link的访问权限,都是这样的:
[Authorize(Roles = "ProductManager", UDCRoles="rootID, ProductManager")] public ActionResult EditTree(int rootID, string whats, string whattypes) { ... return OperateTreeView(...); }UDCRoles="rootID, ProductManager"是说,用url的rootID数值来找UDCable,然后判断其"ProductManager"是否等于当前用户。
用这个属性后Action中可以减少3行(一共才5行,所以3行很多了),而整个代码中有很多这样的三行代码,估计现在有30处左右,都很容易写错造成漏洞。
剩下一个问题,@MFCUI.ImageLink怎么知道这些Action的访问权限呢?
现在的想法是在属性代码中用"Area/Controller/Action"作为Key,权限设置(就是“rootID, ProductManager”)作为值做一个静态缓存,ImageLink会根据自己传入的Url解析出“Area/Controller/Action”并去查找缓存的值,如果找到就根据权限进行判断是否显示为链接)。这样未来只要在Action前面写好属性,所有指向它的链接都会自动判断。
因为之前已经有很多可用的代码了(比如解析A/C/T的代码),所以估计两者加起来大约有10~15行代码就能实现。
估计这些代码两个月后才会排到足够优先级,写好了我共享一下。
总结所有代码结构中的第一块积木是最难的,如果不是我们原来有一些复用了,上面这个访问权限问题解决起来可能需要上百行代码,很容易将就一下就硬编码过去了。
如果我们当年所有View里边的链接都是用<a></a>硬编码的,或用MVC中自带的Hmtl.Link()写的,那么我们也没有勇气和动力来用“这么复杂”的方式来解决这个访问权限问题了。但若干时间后,一旦访问权限变化了,肯定会因为各地的硬编码而出现无数问题,那时候就真的乱了。
UDCable和ImageLink这些都是接近一年半年前产生的,那时候完全没想到会与现在要做的权限控制相关。只能说,如果做对了事情,回报是迟早的。
所以应该随时随地把可复用的东西总结起来,这样反而不觉得累,才能不断在原来的基础上前进。