Springcloud zuul和shiro結合


一.目標
1.外部請求統一從網關zuul進入,並且服務內部互相調用接口要校驗權限

2.cloud和shiro結合,達到單點登錄,和集中一個服務完成權限管理,其他業務服務不需要關注權限如何實現

3.其他服務依然可以控制權限細粒度到接口,如在接口上使用@RequirePermisson等注解,方便開發

二.思路
SpirngCloud zuul網關有兩個作用,一個是分配路由,一個是過濾。

zuul的過濾器作用有限,只能簡單的做一些某個url是否能夠訪問之類的,無法像shiro一樣細粒度到某個用戶是否有某種權限;

shiro單體應用大家都會做,那變成微服務后,難道每個服務都要寫一套shiro框架?這顯然也太麻煩。

1.在zuul服務里用shiro,做成動態url權限控制,就是把訪問哪個url需要用什么權限,寫入數據庫,在過濾器讀取與用戶有的權限作對比;但是服務互相調用校驗就行不通了,因為服務間調用不走zuul

2.寫一個服務專用於shiro認證和授權,包含用戶、權限的curd,暴露出查詢一個用戶擁有什么權限的接口;在其他服務中,都寫一個攔截器拿訪問者token去授權服務拿此用戶的權限,再跟請求的url對比;或者可以自定義注解用aop,注解標注的是訪問此url需要什么權限,遠程調用授權服務接口查詢當前用戶所有權限,與請求的url對比。

但是這個要自己實現攔截器。

3.第二種思路的簡單版本。

寫一個server服務專用於shiro認證和授權,包含用戶、權限的curd,暴露出查詢一個用戶擁有什么權限的接口;

在寫一個client項目打成jar包供其他服務使用,也是用shiro框架,不同於server服務的是,在realm中只有授權方法,沒有認證方法,並且授權方法的實現是去server遠程查詢權限,再返回給client項目的安全管理器。且client的登錄接口寫成server的登錄接口,這樣未登錄的用戶都會跳轉到server登錄,想辦法保存下原路徑,登錄成功后再返回原服務;同時做成session共享

普通業務服務只需要依賴於client,就相當於每個服務都有了一套shiro。

這種思路來自於《跟我學shiro》的多項目集中權限,其實想想這種思路是可以的,shiro本質也是靠攔截器進行權限校驗,雖然相當於每個服務都開啟了一套shiro,但也就是容器中多了一些shiro攔截器和實例,而且可以用shiro的各種功能,開發方便。可以完成我們的三個目標。

三.其他思路
1.分布式session

用戶在網關進行登錄認證;如果通過,將用戶信息存在第三方組件,mysql、redis;后端其他服務可以通過第三方組件拿到用戶數據。
這種方案值得推薦,方便擴展,但依賴於第三方組件,注意第三方組件的高可用。
2.客戶端token與網關結合

服務器無session,將用戶信息存儲在token,比如JWT。

了解JWThttps://www.cnblogs.com/cjsblog/p/9277677.html

客戶端攜帶用jwt加密的token,訪問網關,token攜帶了用戶的信息
網關對token認證和校驗
校驗通過網關后,請求攜帶token到具體服務,可以校驗具體的url權限
如果用戶信息量大,則不適合,因為都是存儲在客戶端的;並且token要在網關注注銷
zuul + OATHU2+JWT
3.瀏覽器cookie和網關結合。

和上述方案相同,區別是用戶信息完全放在cookie,不用token
---------------------------------------------------------

外加一段優秀的對話:

A:大佬有沒有想過用單點登錄sso ,把登錄寫成一個服務shiro在這個服務里面作用,需要訪問別的服務的時候zuul反向代理到sso的服務進行認證登錄,可這樣我現在遇到這樣的問題,shiro的授權怎么才能被其他的服務知道,並且在頁面進行細粒度級別標簽控制攔截

B 回復 A: 嗯。不經過。zuul是給外部調用使用的。。

C回復 A: 看文章,服務之間互相訪問是不經過zuul的,只有外部請求訪問才通過zull

B回復 A: 其實有簡單的方法可以實現類似的目標。就是把個人信息放在Redis或者其他nosql庫里,同時放入的還有個人的權限信息,包括可訪問的資源信息和角色。然后可以用zuul來進行過濾判斷。這樣寫,就很簡單了。不需要用到shiro,也可以避免很多問題。

B 我現在的想法是吧feignServer單獨寫成服務,然后將接暴露,其他服務調用這個接口,來進行判斷權限。但是這樣,會不會有網絡延遲發生?

B回復 E: 我是返回統一的result的,里面封裝了flag標識。。把shiro單獨寫成服務,有一個好處就是讓其他服務不用再集成shiro,只要去訪問shiro這個服務就能知道是否有權限了。其他服務如果要判斷的話,就去調用接口就好了。 

B回復 A: 可行。已經實現了。feignClient服務暴露出2個接口,權限和角色的認證接口就可以了。注意feign的無狀態認證。

A回復 B: 大佬,這樣可行,可是別的服務需要授權的時候怎么辦

C回復 B: 我認為本質上就是這個思路,cloud里面每個頁面上的請求都要經過網關轉發一次,那也要有網絡延遲了,沒辦法。適當加上緩存吧,不用每次都去請求server判斷權限

 

 

 

-----------------------希望可以幫助到你么


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM