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