在SpringCloud架構中,實現授權功能有兩種實現方式:
- 在網關層進行授權
- 由后端微服務自己授權
兩種方式在此系列文章中都有實現方案,那么問題來了:哪種才是最優方案,哪種方案更合理呢?
很抱歉,看完這篇文章你也不一定能得到你想要的答案,因為結論是並沒有最優方案,兩種方案各有千秋,只有根據自身業務選擇對應的方案。本文我們將兩種方案做一個簡單對比,以便大伙在做方案決策有個選擇參考。
解決方案對比
首先我們看看兩種方案實現的原理:如果對具體實現方式有疑問的同學可以參考這篇文章:SpringCloud Alibaba微服務實戰十九 - 集成RBAC授權
網關授權
基於網關授權我們又叫基於路徑匹配器授權,請求在經過網關的時候校驗當前請求的路徑是否在用戶擁有的資源路徑中。
在基於路徑匹配器授權時需要考慮restful風格的訪問路徑,如 /account-service/blog/user/{id}
或 /account-service/blog/**
等,所以在網關進行授權主要是基於通配符匹配。
微服務授權
微服務授權我們又叫基於方法攔截,在資源上打上對應的方法標識然后分配給用戶。在請求方法上通過對應的注解判斷當前用戶是否有訪問此方法的權限。如SpringSecurity中的 @PreAuthorize("hasAuthority('')")
注解,Shiro中的 @RequiresPermissions('')
注解。不管是SpringSecurity還是Shiro他們實現原理都是基於關鍵字完全匹配。
優缺點對比
網關授權
優點
使用網關授權的優點很明顯,后端所有微服務只需要是普通的服務即可,不再需要依賴權限那一套。
缺點
-
通配符匹配在網關做性能比較差,通配符要拆分,先匹配前綴,前綴匹配了再匹配通配符。
這里大家可以看看org.springframework.util.AntPathMatcher#doMatch()
的實現邏輯。 -
對於Restful風格的URL路徑,不能精細化控制權限
例如一個微服務有如下API
GET /v1/pb/user
POST /v1/pb/user
PUT /v1/pb/user
這樣在網關通過request.getURI().getPath()
方法獲取到用戶請求路徑的時候都是同一個地址,給一個用戶授予/v1/pb/user
權限后他就擁有了GET
、PUT
、POST
三種不同權限,很顯然這樣不能滿足精細權限控制。至於如何解決這個問題,原來專門寫過一篇文章討論,感興趣的同學可以看看:SpringCloud Alibaba微服務實戰二十五 - Restful接口攔截
微服務授權
優點:
上面提到網關授權的缺點實際上是微服務授權的優點,基於方法攔截是完全匹配,cpu消耗很少,而且也不存在RestFul的問題。
缺點:
實現較為復雜,在 SpringSecurity Oauth2
體系中需要全部引入資源服務器相關配置,所以一般會建立一個單獨的資源服務器模塊,這也是系列文章下篇內容需要解決的問題。
結論
這里我們嘗試對兩種實現方案做一個總結,如果系統功能、業務模塊不是很多可以采用網關授權模式,這樣實現最簡單也最方便,雖然存在Restful風格不能精細化權限控制問題,但是我們加一個Method字段就可以解決。
如果你的系統規模比較大,有很多資源需要授權那就建議采用微服務授權模式,為了避免每個微服務都需要處理權限校驗的邏輯,我們需要抽取一個公共的權限認證模塊供后端服務引用。