|
前言
如何實(shí)現(xiàn)一個(gè)高效簡單的系統(tǒng)權(quán)限體系是我們長期以來都在思考的問題,也是最近一年來我思考得最多的問題,我們所期望的權(quán)限都是應(yīng)當(dāng)能夠根據(jù)應(yīng)用的需要不斷添加和擴(kuò)展的權(quán)限,并且最好能夠以最簡單的方式來支持,那就最好不過了。
內(nèi)容
- 什么是權(quán)限系統(tǒng)
- 一個(gè)簡單的設(shè)計(jì)
- 基于角色的訪問
- 最初的數(shù)據(jù)權(quán)限
- 更好的解決方法
- 最近的戰(zhàn)役
- 總結(jié)
什么是權(quán)限系統(tǒng)
那么我們需要一個(gè)什么樣的權(quán)限系統(tǒng)呢或者說什么是權(quán)限,我查看了很多的相關(guān)資料想要試圖解決這個(gè)問題,最后看一個(gè)最簡單最明確的答案"安全問題就是解決誰對什么能夠進(jìn)行什么控制的問題”。如何來分析這段話呢,我敢保證這是我見過的最明確也是最抽象的需求,通過什么樣的方式來分析和解決這個(gè)需求問題呢。
而對復(fù)雜的問題我們必須拿出強(qiáng)大武器才行啊,對于不明確的概念我們首先需要完成的是將“概念明確化”先將這段話中不明確的代詞進(jìn)行明確化,那么我們就從第一個(gè)代詞開始“誰”是指什么呢,“員工”,“用戶”,“領(lǐng)導(dǎo)”,...,還是什么其它呢,我想對于不同的問題我想需要采用不同的概念,如果這個(gè)系統(tǒng)只是用于解決公司內(nèi)容的相關(guān)問題,那么這里使用“員工”最好不過,如果專門用于解決“領(lǐng)導(dǎo)”的個(gè)人問題,那么“領(lǐng)導(dǎo)”也不錯(cuò)。這里主要需要考慮我們所面臨問題和抽象的層次,同時(shí)還需考慮到具體應(yīng)用的行業(yè)標(biāo)準(zhǔn)。對于需要大多數(shù)情況采用“用戶”或“當(dāng)前用戶”是一個(gè)比較好抽象,我們這里采用“當(dāng)前用戶”,這樣比“用戶”更明確一些,那么這段需求就變成了“安全問題就是解決當(dāng)前用戶對什么能夠進(jìn)行什么控制的問題”。
好解決了第一個(gè)抽象之后,對于其它問題我們同樣采用相關(guān)的方式來進(jìn)行分析,“當(dāng)前用戶對什么” 之中的“什么”當(dāng)前相關(guān)問題的抽象層次之中基本上都是采用“安全資源對象”來進(jìn)行抽象的,當(dāng)然也可以根據(jù)實(shí)際處理的問題進(jìn)行抽象,我們這里主要是考慮通用性。而對于“能夠進(jìn)行什么訪問”之中的“什么”這里也需要根據(jù)相關(guān)問題的來進(jìn)行設(shè)定,這里我們采用“訪問或拒絕”,那么這一段需求就變成“安全問題就是解決當(dāng)前用戶能夠?qū)Y源對象進(jìn)行訪問或拒絕控制的問題”,如果實(shí)現(xiàn)需要就是對功能進(jìn)行控制還可以說成是“安全問題就是解決當(dāng)前用戶能夠?qū)δ苓M(jìn)行訪問或拒絕控制的問題"。
一個(gè)簡單的設(shè)計(jì)
了解了問題的本質(zhì)后,我們需要做的就是要完成它,那么怎樣來完成這呢。首先我們需要從需求之中將我們領(lǐng)域模型分離出來:
如果是一個(gè)簡單的權(quán)限設(shè)計(jì),那么整個(gè)權(quán)限系統(tǒng)不這樣就完成了,非常的簡單明了(對于這里各對象所需要領(lǐng)域訪問就不在說明)。
基于角色的訪問
當(dāng)簡單的設(shè)計(jì)使用的用戶數(shù)量一天一天的增加的時(shí)候,我們發(fā)現(xiàn)給一個(gè)一個(gè)用戶分別進(jìn)行權(quán)限的設(shè)置是一件非常困難的工作。好,看來是我們修改設(shè)計(jì)的時(shí)候到了。最先想到的是我們必須對用戶進(jìn)行分組,將對用戶的訪問授權(quán)設(shè)置到這些組之中。好,那我們就設(shè)置一個(gè)用戶組,通過用戶組來設(shè)置吧,但我們又會(huì)想到在實(shí)際的業(yè)務(wù)之中一個(gè)多崗的情況很多啊,那么怎么辦呢,同時(shí)如果能夠以現(xiàn)實(shí)際之中公司的實(shí)際情況設(shè)置權(quán)限最好不過,因?yàn)檫@樣對于系統(tǒng)的管理人員來說,只需要了解公司內(nèi)部的情況就可以了,那么怎么樣來協(xié)調(diào)這兩個(gè)問題呢。
其實(shí)這個(gè)問題在安全設(shè)計(jì)的前輩們早已想到應(yīng)對之策,就是將這些對象抽象以“角色”來表示這些抽象的概念。那么加入的角色對于我們的領(lǐng)域模型帶來了什么樣的變化呢?
這樣對于我們的管理來說真的大大的簡化了啊,但這就完全的滿足了我們的條件了嗎?
最初的數(shù)據(jù)權(quán)限
當(dāng)我們正在為自己的設(shè)計(jì)而高興的時(shí)候新的問題又來了,怎么回事呢。小鄭啊,北美銷售部只能夠管理北美的銷售啊,發(fā)動(dòng)機(jī)事業(yè)部只能夠銷售發(fā)動(dòng)機(jī)產(chǎn)品啊,你那個(gè)程序是怎么回事啊,怎么都能夠看啊,還有怎么部長都能夠?qū)徟?00W以上的定單啊。
啊,我快要完蛋了。
好,兵來將擋,水來土淹什么問題都能不倒我。
看來我們還必須要設(shè)計(jì)滿足數(shù)據(jù)權(quán)限的要求才行啊。
好吧,那我怎么樣子來實(shí)現(xiàn)呢...?好吧,我應(yīng)在安全資源之中加一個(gè)數(shù)據(jù)規(guī)格,在訪問控制之中加入一個(gè)值的設(shè)定,怎么樣,這下行了吧?
好吧,現(xiàn)在就看我來實(shí)現(xiàn)它吧,以我精湛的技術(shù)。
啊,什么,一個(gè)用戶多個(gè)角色,不同的角色有不同的數(shù)據(jù)規(guī)則控制。啊,還需要數(shù)據(jù)控制的合并,沒事我們使用提供者模式來解決,實(shí)現(xiàn)不同的合并提供者,使用提供者來合并結(jié)果。
啊,什么,怎么樣轉(zhuǎn)換到數(shù)據(jù)訪問的控制,沒事,咱們硬編碼。
啊,不可能吧,連個(gè)獲取操作都需要進(jìn)行控制啊。
啊,我不行了。倒在了黎民前了晚上。
更好的解決方法
如果沒有能夠?qū)?shù)據(jù)權(quán)限進(jìn)行詳細(xì)的分析,那么一定會(huì)在倒在黎明的前夜,沒有完整的解決方法,那是不行的。好,我們先來分析一個(gè)數(shù)據(jù)權(quán)限的要求,這里我只能夠?qū)懗鑫覍τ谶@部分的分析,數(shù)據(jù)權(quán)限的限制總是:{實(shí)體屬性值 條件 允許值}這三個(gè)產(chǎn)品分組成,如:數(shù)據(jù)規(guī)則,銷售部長只能夠?qū)徍虽N售金額小于100W的定單這里的三者是{銷售定單.合計(jì)金額 小于 100W}, 銷售員小張只能夠銷售摩托車產(chǎn)品,這其中的三者是{銷售項(xiàng)目.產(chǎn)品類型 屬于 摩托車)
所以這里對于數(shù)據(jù)的限制都只包括三個(gè)要素:領(lǐng)域?qū)嶓w屬性 條件 允許值。這三者的結(jié)合就限制的約束。那么這三都之中都有哪些情況呢?
領(lǐng)域?qū)嶓w屬性:這個(gè)基本上都沒有什么變化。
條件:如果是條件就只有那么幾種,有大于,小于,等于,實(shí)體范圍等等。
允許值:允許值這里經(jīng)過我的分析包括三種情況{設(shè)置值,用戶屬性相關(guān)值,業(yè)務(wù)設(shè)定值}
這三種情況分別使用于以下情況:設(shè)置值表示是我們是設(shè)置權(quán)限的時(shí)候直接進(jìn)行設(shè)置的如100W,用戶屬性相關(guān)值表示與用戶的某一個(gè)屬性相關(guān),如:部門,職務(wù)等。還有一種就是業(yè)務(wù)相關(guān)的情況,這類情況相當(dāng)于是在業(yè)務(wù)之中設(shè)置數(shù)據(jù)。這類問題在SAP之中設(shè)置比較多,感興趣的可以去了解一下SAP之中的相關(guān)設(shè)置。
在這里對于條件的設(shè)置基本上都只有固定的幾種,可以采用枚舉的方式來進(jìn)行,而對于充許值這一個(gè)點(diǎn),因?yàn)椴煌臉I(yè)務(wù)所需要的不同的數(shù)據(jù)和相關(guān)內(nèi)容不想同,因此,將這一個(gè)允許值的獲取設(shè)置為一個(gè)相關(guān)的接口來進(jìn)行,而在進(jìn)行配置的時(shí)候只設(shè)置一個(gè)相關(guān)值,由接口去解晰和獲取。這時(shí)候的領(lǐng)域模型圖如下:
最后的戰(zhàn)役
在解決了領(lǐng)域問題之后,我們還需要考慮提供什么方式來獲取這些服務(wù),這里首先需要考慮使用權(quán)限的兩種情況,一種是當(dāng)需要顯示相關(guān)界面時(shí); 二是當(dāng)需要執(zhí)行相關(guān)操作時(shí)。
- 第一種情況:當(dāng)我們進(jìn)入到提供定單的界面,那么顯示出來的相關(guān)產(chǎn)品肯定是我們能夠允許提供的產(chǎn)品,顯示出來的國家也是我們能夠進(jìn)行銷售的國家。
- 第二種情況:當(dāng)我們提交定單時(shí),提供的內(nèi)容必須進(jìn)行檢查。
對于第一種情況:我們在執(zhí)行GetCountries()和GetProducts()這兩個(gè)方式的內(nèi)部就必須執(zhí)行條件的限制,那么如何來實(shí)現(xiàn)這個(gè)條件的限制呢。這里必須要通過一種方式讓GetCountries了解到當(dāng)前正自于那一個(gè)安全的環(huán)境之中,再獲取獲取相應(yīng)的數(shù)據(jù)限制,查看這個(gè)限制的實(shí)體是否為Country如果是那么是那個(gè)條件進(jìn)行的設(shè)置編號,國家名稱,上級部門。再將這些條件轉(zhuǎn)換為對應(yīng)的SQL來進(jìn)行限制,如果這些方法都是通過硬編號來完成,那么一定是一個(gè)復(fù)雜的工作,好在現(xiàn)在的ORM工具直接就支持領(lǐng)域?qū)嶓w,屬性,條件等內(nèi)容,直接可以將這些配置的安全值設(shè)置到這些訪問之上,這樣就可以完成整個(gè)數(shù)據(jù)限制,同時(shí)還需要考慮到如果是在多個(gè)不同的應(yīng)用之間設(shè)置這些服務(wù),還需要考慮到安全的層次關(guān)系,在多個(gè)層次之中使用和設(shè)置多層安全環(huán)境。這就必須使用一個(gè)對應(yīng)的環(huán)境管理類來管理這些環(huán)境。對于這個(gè)環(huán)境可以采用SecurityContext來表示,而對于這個(gè)環(huán)境的管理類使用SecrityContextManager的線程單例模式來進(jìn)行設(shè)置。在實(shí)現(xiàn)的過程之中,如果需要一個(gè)新的安全環(huán)境則建立一個(gè)新的SecurityContext,在新實(shí)例的SecurityContext之中將自己注冊到SecurityContextManager的單實(shí)例之中。同時(shí)在建立SecurityContext時(shí)傳入相關(guān)的安全資源對象,對這些對象進(jìn)行安全檢查,如果沒有進(jìn)行授權(quán)則引發(fā)System.Security.SecurityException對象。
在開發(fā)數(shù)據(jù)訪問層時(shí),通過SecurityContextManager.Instance來獲取如:Employee實(shí)體的的限制,通過前面所設(shè)計(jì)的獲取允許值提供者接口來獲取允許的值,并且將屬性,條件,允許值,轉(zhuǎn)換為對應(yīng)的SQL來進(jìn)行調(diào)用。這樣就實(shí)現(xiàn)了多層次的數(shù)據(jù)權(quán)限。如果對應(yīng)的ORM工具能夠直接支持條件的設(shè)置則可以將這個(gè)工作直接編寫對應(yīng)的轉(zhuǎn)換器來進(jìn)行轉(zhuǎn)換,這樣可以大大的提高開發(fā)的效率,并且還可以根據(jù)需要對領(lǐng)域成員進(jìn)行新的數(shù)據(jù)約束,而不必修改應(yīng)用程序。
同時(shí)如果所需要限制的數(shù)據(jù)資源不是領(lǐng)域?qū)嶓w中的數(shù)據(jù),也可以通過這種方式來設(shè)置自己的數(shù)據(jù)范圍的檢查。
總結(jié)
本文主要是介紹一種安全的實(shí)現(xiàn)方式,安全不是一個(gè)簡單到只需要在某一具體層就能夠解決的問題,而需要在多個(gè)層次進(jìn)行多層次的設(shè)置。形成類似于IIS式的多層次,多角度權(quán)限設(shè)置,這里只是給出了其中最為核心的內(nèi)容,沒有給出具體的代碼,這主要是因?yàn)椴荒軌蚬脊緝?nèi)部開發(fā)的程序,所以可能對于完整的理解有所不足。
對本文有什么好的意見或見意請大家多指教。
it知識庫:大話權(quán)限設(shè)計(jì),轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時(shí)間聯(lián)系我們修改或刪除,多謝。