如何使用Defender優雅的管理許可權?
何為許可權管理
許可權管理已經不知不覺深入到了我們生活的每一個角落,例如地鐵進站的閘機,高速公路上的過路費,停車場的槓桿等等等等。
作為一名開發人員,許可權二字對我們的映像更加深刻,無論任何系統,都多多少少與許可權管理會沾上關係!什麼?你的系統和許可權不沾邊......好吧,你的程式碼拉取許可權總得有吧!如果還沒有的話,你登上掘金看到這篇文章並點了一個贊這個過程就需要好多次許可權校驗。好了扯遠了,我們迴歸正題,這裡使用一張圖來簡單展示web系統的許可權是什麼樣子:
看完之後,是不是感覺很簡單,不錯,許可權管理並不難,我們只需要將校驗這一環節進行開發即可,實現方式也有很多種:
方案一:元件封裝
我們可以將許可權校驗的整個過程元件化,例如元件名為AuthComponent
,之後再所有需要許可權校驗的介面對應的方法的開頭,呼叫AuthComponent
的verify
方法進行校驗,根據結果做不同的業務處理!
- 優點:貌似能達到主要目的,而且非常靈活~
- 缺點:程式碼冗餘,低內聚,高耦合,不易於維護。
方案二:通用處理
在方案一的基礎上我們稍加改造,例如使用AOP
對需要校驗的介面做個切面,在方法執行前我們使用AuthComponent
校驗一下即可,這樣我們的程式碼就更方便維護了!
- 優點:彌補了方案一的缺點。
- 缺點:太過通用化,很難相容所有的情況,不靈活。
方案三:自定義註解
我們將方案一和方案二結合一下,取一靈活,取二通用,我們自定義一個名為@Auth
的註解,並且它需要傳一個引數,我們這裡直徑定義為列舉類Level
,簡單結構如下:
public enum Level { LOGIN, ADMIN }
複製程式碼
之後我們定義一個註解切面,切向攜帶@Auth
的方法,在方法執行前根據value值的內容,也就是Level
的值去做不同的許可權管理即可。
- 優點:靈活可控,通用性還行。
- 缺點:缺乏元件化,結構零散,不易複用,對於多種場景下需要制定多個切面,不優雅!
方案四:使用框架
這是最簡單的方法,例如優秀的開源shiro
spring-Security
等都可以滿足我們的需求,唯一的區別是框架的輕重及使用方式!
如何更優雅的管理許可權
想必很多同學都在使用第四種方案,也有不少的小夥伴在使用方案三,對於缺點明顯的方案一和二,使用的應該很少。
如果我們的服務並不需要那麼重的許可權管理框架去解決許可權問題,又不想不優雅的自定義註解去實現時,我們該怎麼辦呢?
不妨試試 Defender
Defender是什麼
defender
是一款全面擁抱spring-boot
的輕量級,高靈活,高可用的許可權框架。如果日常中我們需要更加便捷的對服務增加許可權管理,那麼defender
正合適!
它可以免除我們重複編寫自定義註解和切面,只需要呼叫簡單的API即可靈活的指定不同模式的防禦網絡。
defender
提供很多種防禦模式,我們可以通過呼叫簡單的api是使用構建不同模式的校驗器,從而迅速完成許可權的管理:
@Configuration
@EnableDefender("* org.nico.trap.controller..*.*(..)")
public class DefenderTestConfig {
@Bean
public Defender init(){
return Defender.getInstance()
.registry(Guarder.builder(GuarderType.URI)
.pattern("POST /user/*")
.preventer(caller -> {
return caller.getRequest().getHeader("token") == null
? Result.pass() : Result.notpass("error");
}))
.ready();
}
}
複製程式碼
上述程式碼的作用是對請求符合POST
型別且URI字首為/user/
的所有介面做了許可權管理。
另外,我們可以使用lambda
簡單完成許可權校驗邏輯,又或者使用匿名類實現複雜校驗邏輯:
Guarder.builder(GuarderType.ANNOTATION)
.pattern("org.nico.trap.controller")
.preventer(new AbstractPreventer() {
@Autowired
private AuthComponent authComponent;
@Override
public Result detection(Caller caller) {
String identity = caller.getAccess().value();
if(! identity.equals(AuthConst.VISITOR)) {
UserBo user = authComponent.getUser();
if(user != null) {
if(identity.equals(AuthConst.ADMIN)){
if(user.getRuleType() == null) {
return Result.notpass(new ResponseVo<>(ResponseCode.ERROR_ON_USER_IDENTITY_MISMATCH));
}
}
}else {
return Result.notpass(new ResponseVo<>(ResponseCode.ERROR_ON_LOGIN_INVALID));
}
}
return Result.pass();
}
})
複製程式碼
其中GuarderType.URI
和GuarderType.ANNOTATION
分別代表URI ANT匹配模式和註解模式,後者是方案三的實現,defender
提供簡單優雅的api將各種模式的許可權校驗方式集合在一起。
相比shiro
、spring-security
,defender
顯得更加輕便靈活,因為它並沒有提供一系列許可權更具體的管理實現,而是將校驗的實現開放一個介面面向開發者,總體程式碼大小不超過21k
,顯然對於輕量級的許可權管理,defender
更加適合!
defender
剛剛起步,如果大家有興趣可以將之整合在您的開發環境嘗一下鮮,專案地址如下
官方也提供有簡單的使用文件
如果您感覺不錯,也想參與貢獻