當前位置: 妍妍網 > 碼農

微服務 Token 鑒權設計的幾種方案

2024-03-22碼農

點選關註公眾號,Java幹貨 及時送達 👇

  • Token透傳(不推薦)

  • Fegin內部呼叫方式

  • Dubbo內部呼叫方式

  • Spring Boot Web + Dubbo內部呼叫方式

  • 常規模式

  • 與K8S整合

  • Token透傳(不推薦)

    剛開始接觸微服務時網上給的方案大都數是透過透傳Token做鑒權,但我認為這種方式不是很妥當。接著往下看:

    圖片

    這種方式透過透傳Token使得各微服務都能獲取到當前登入人資訊,在程式碼編寫上確實可能會方便,但我認為這不是一種很好的設計方式。

    原因一:內部API與外部API混合在一起不太好區分。

    原因二:內部呼叫的微服務API因該具備無狀態性質,這樣才能保證方法的原子性以提高程式碼復用率。

    換句話說:B服務提供API時不因該關心當前是否為登入狀態,登入狀態應該由路由中的第一個服務校驗維護,在呼叫後續服務時應該顯示的傳入相關參數。比如以下場景:

    場景一:使用者簽到添加積分

    場景二:後台管理員給使用者手動添加積分

    場景三:分布式排程批次增加使用者積分

    根據需求積分服務提供了一個給使用者添加積分的API,如果你的API是透過獲取的當前登入使用者ID增加的積分,那麽面對場景二時你需要重新編寫一個給使用者添加積分的API,因為當前登入的是後台管理員而不是使用者(程式碼復用率較低)

    不透傳數據,顯示的提供入參

    圖片

    路由到達的第一個服務已經對Token進行了解析認證並將userId顯示的傳遞給了後續服務,後續服務不需要再對token進行解析認證。根據1.1的三個場景只需要提供一個入參包含userId的API,保證了函式的原子性提供程式碼復用率。

    註意: 提供的API不能暴露給外網,我們需要在路徑上做區分,避免外網非法存取內部API。我們可以訂好內部呼叫API路徑規則,如: /api/inside/\*\* 。在閘道器層拒絕內部呼叫API請求的存取。

    統一授權

    統一授權是指:將API鑒權集中在套用閘道器上

    Fegin內部呼叫方式

    Spring Cloud Gateway + Fegin內部呼叫,集中在Gateway上做統一認證鑒權,鑒權後在請求頭中添加鑒權後的資訊轉發給後續服務,如:userId等。。。

    圖片

    缺點:A服務呼叫B服務時,B服務需要寫一個內部呼叫的Controller介面A服務才能透過Fegin呼叫到B服務,增加了程式碼量(這裏的設計方案是內部呼叫與外部呼叫Controller是分開的)

    Dubbo內部呼叫方式

    Spring Cloud Gateway + Dubbo內部呼叫,集中在Gateway上做統一認證鑒權,鑒權後在請求頭中添加鑒權後的資訊轉發給後續服務,如:userId等。。。

    優點:與第一種相比不需要額外編寫一個Controller介面,只有本地service與遠端DubboService的區別,程式碼更簡潔。

    缺點:計畫技術棧略微增加了復雜度。

    圖片

    Spring Boot Web + Dubbo內部呼叫方式

    這裏的設計方案直接去掉了Gateway,直接使用了一個Spring Boot Web計畫來代替Gateway。但需要註意的是應該將Web計畫的容器換成Undertow,因為Tomcat是阻塞式的容器,不換也不是不行,但吞吐量可能會少一下,Undertow是非阻塞式的容器,可以與Gateway到達相同的效果。(非阻塞式:當請求為執行緒進入阻塞狀態時,當前執行緒會被掛起,當前的計算資源會去做別的事情,當被掛起的執行緒收到響應時才會被繼續執行,壓榨CPU用更少的資源做更多的事情,但並不會提升效能)

    因為去掉了Gateway我們需要將所有服務的Controller整合到Web套用,然後在這個Web套用上做統一認證授權。如果將所有程式碼寫到Web套用中,這樣可能不合適,我們可以選擇每個服務建立一個Controller模組,Web閘道器服務只有一個啟動類,透過依賴的方式整合所有服務的Controller。

    優點:簡化了計畫結構,所有服務只有service程式碼。效能壓測時不用考慮Gateway的執行緒池使用情況,業務服務只需要考慮Dubbo執行緒池的使用情況。

    缺點:沒辦法透過配置中心動態調整路由。比如說增加了一個服務Gateway可以不重新開機透過配置中心增加路由配置即可。

    圖片

    非統一授權

    非統一授權:不在套用閘道器上整合鑒權,閘道器只有單一的路由轉發業務。各位服務都有自己的鑒權方式,當然也可以透過jar包的方式統一各服務的鑒權方式。

    常規模式

    透過編寫通用的鑒權模組,各服務整合該模組。該模組具備以下功能:

    1. JWT Token解析

    2. 許可權校驗攔截

    3. 緩存(本地緩存\Redis緩存)

    這種模式更適合大型計畫團隊,可能各微服務都由一個計畫組負責。各服務維護自己的許可權規則(這裏指的是許可權規則數據,規則是統一的)

    圖片

    該模式下由於套用閘道器比較輕量級,不再涉及復雜的鑒權流程,使得計畫部署可以更靈活,當我們使用K8S部署計畫時,我們可以將套用閘道器替換成K8S中的Ingress閘道器。

    我們先看常規模式部署在K8S中完整的鏈路:

    圖片

    當使用者存取時會先到達K8S Ingress閘道器透過套用閘道器Service的負載均衡呼叫套用閘道器,套用閘道器需要透過註冊中心獲取服務註冊列表,透過服務註冊列表負載均衡到後續服務。

    與K8S整合

    我們再來看看將套用閘道器替換成K8S中的Ingress閘道器的完整鏈路:

    圖片

    這裏不僅只是去掉了套用閘道器,同時我們透過K8S Service 負載均衡的能力去掉了註冊中心。減少了我們部署微服務時還要額外搭建一套註冊中心。同時減少了一層沒必要的轉發。至於K8S中的Service,大家可以理解成一個原生的host假網域名稱,比如我們在K8S給商品建立一個Service,名稱為:goods-svc。那麽我們可以透過goods-svc直連。如:

    1. http://goods-svc:8080/api/goods/info/10001

    2. dubbo://goods-svc:20880

    方案沒有對錯,選擇適合自己的就是最好的。

    來源:juejin.cn/post/7329352197837029385


    END


    看完本文有收獲?請轉發分享給更多人

    關註「Java編程鴨」,提升Java技能

    關註Java編程鴨微信公眾號,後台回復:碼農大禮包可以獲取最新整理的技術資料一份。涵蓋Java 框架學習、架構師學習等!

    文章有幫助的話,在看,轉發吧。

    謝謝支持喲 (*^__^*)