Posted on 2007-01-02 12:11
江上一葉舟 閱讀(7422)
評論(21) 編輯 收藏 所屬分類:
軟件藝術
最近項目的項目很奇怪,一個大項目(系統)里包含了很多小的子系統,而這些子系統中都有權限控制的部分,這件事情挺讓我頭痛的,記得一年前在沈陽,我曾經有一段時間也因因這個問題而疲于奔命,為什么說疲于奔命呢?由于當時項目進度不允許,導致最終系統權限模塊草草了事,每個模塊都是由讀權限字符串來控制用戶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進制的權限判別代碼,雖然配置較麻煩,寫完代碼還要寫文檔說明,不過也解決了權限繁雜又多的問題,暫時就這樣了,嘿嘿,以后有空再研究。