如何實現(xiàn)高效的動態(tài)鑒權(quán)
?一、概述
Spring Security 是 Spring 框架內(nèi)高度可定制化的安全框架,也是 Spring 應(yīng)用的標(biāo)準(zhǔn)安全框架,提供了包括認(rèn)證和鑒權(quán)在內(nèi)的兩大部分。其高度集成于 Spring 框架,無需引入第三方擴(kuò)展模塊,可以避? 免大量的數(shù)據(jù)接口適配問題,大幅度減少開發(fā)成本和時間。
如下圖所示,Spring Security 的認(rèn)證鑒權(quán)過程實際上位于請求過濾器和攔截器中,在請求通過了所有的過濾器和攔截器之后才會進(jìn)行 API 適配。換言之,定制 Spring Security 就是修改過濾鏈中的各種過濾器和攔截器。
認(rèn)證過程是圖中綠色的部分,Spring Security 提供了非常多的認(rèn)證方式,如密碼認(rèn)證、預(yù)認(rèn)證等;橙色的部分是動態(tài)鑒權(quán)部分,其內(nèi)置的 Security Interceptor 會將請求委托給各個具體的 AccessDecisionManager 進(jìn)行鑒權(quán)。

在 Spring Security 中,AccessDecisionManager 是以投票器為藍(lán)本進(jìn)行的鑒權(quán):Manager 下面會有多個 AccessDecisionVoter,每個 Voter 將結(jié)果返回至 Manager,最后由 Manager 確定是否授予權(quán)限。
Manager 共有三類:
AffirmativeBased 一票通過制(默認(rèn)選項)
UnanimousBased 一票反對制
ConsensusBased 少數(shù)服從多數(shù)制
之所以會用投票器,一是方便添加和擴(kuò)展 voters,二是量化鑒權(quán)結(jié)果簡化框架實現(xiàn)。
二、鑒權(quán)模塊構(gòu)建
根據(jù)概述部分,我們可修改的地方有很多,例如 FilterSecurityInterceptor, AccessDecisionManager, AccessDecisionVoter。但是無論修改 Interceptor 還是 Manager 都非常花費時間,因此我們選擇直接添加一個新的 Voter 來進(jìn)行動態(tài)鑒權(quán)。
在這里我們使用 AffirmativeBased 投票器進(jìn)行投票,是因為進(jìn)行自定義過濾的過程中,我們并沒有包含 Spring 默認(rèn)的屬性,因此 WebExpressionVoter 會自動棄權(quán),剩余步驟自然由我們自己的投票器 UserAccessDecisionVoter 進(jìn)行投票和鑒權(quán)。
該應(yīng)用是基于角色賦予不同的權(quán)限,在后續(xù)進(jìn)行權(quán)限判定的過程中,包括但不限于以下兩種解決方案:
將所有需要判定的 URI 放入數(shù)據(jù)庫,檢查權(quán)限時取出;
設(shè)計文檔中規(guī)定涉及到的操作和 URI 模版,相互間獨立不干涉;鑒權(quán)時用正則表達(dá)式進(jìn)行判斷;后續(xù)添加的新操作需要依據(jù)改模版構(gòu)建 URI。
第一種策略應(yīng)用模塊眾多,后續(xù)需要新增大量人員,將需要判定的 URI 放入數(shù)據(jù)庫并用表進(jìn)行連接,可能導(dǎo)致占用較多的數(shù)據(jù)庫存儲空間,并不合適。因此我們采用第二種策略進(jìn)行操作 URI 的判定,缺點是編碼量比較大,優(yōu)點是不會占用太多的額外存儲空間。
在構(gòu)建自定義鑒權(quán)投票器的過程中,可能會發(fā)現(xiàn)一些需要直接放行的操作,涉及到這部分操作的 URI 我們將其放在配置文件中,并在構(gòu)建過濾鏈的時候進(jìn)行注入,達(dá)到繞開投票的目的。
三、總結(jié)
以上便是一個根據(jù)?SpringBoot DecisionVoter?自定義動態(tài)鑒權(quán)的例子,具體鑒權(quán)邏輯和各種細(xì)節(jié)需要根據(jù)不同的需求進(jìn)行不同定制化操作,同時需要注意在進(jìn)行定制化操作時,要保證鑒權(quán)過程的高效性和安全性,避免可能存在的安全漏洞和性能問題。此外,還需要考慮系統(tǒng)的可擴(kuò)展性和可維護(hù)性,以便在未來的需求變更或升級過程中能夠方便地進(jìn)行擴(kuò)展和維護(hù)。