前言:之前的文章有講過微服務的許可權系列和閘道器實現,都是孤立存在,本文將整合後端服務與閘道器、許可權系統。安全許可權部分的實現還講解了基於前置驗證的方式實現,但是由於與業務聯絡比較緊密,沒有具體的示例。業務許可權與業務聯絡非常密切,本次的整合專案將會把這部分的操作許可權校驗實現基於具體的業務服務。
在認證鑑權與api許可權控制在微服務架構中的設計與實現系列文章中,講解了在微服務架構中auth系統的授權認證和鑑權。在微服務網關中,講解了基於netflix-zuul元件實現的微服務閘道器。下面我們看一下這次整合的架構圖。
微服務架構許可權
整個流程分為兩類:
第一類其實比較簡單,在講解認證鑑權與api許可權控制在微服務架構中的設計與實現就基本實現,現在要做的是與閘道器進行結合;第二類中,我們新建了乙個後端服務,與閘道器、auth系統整合。
下面對整合專案涉及到的三個服務分別介紹。閘道器和auth服務的實現已經講過,本文主要講下這兩個服務進行整合需要的改動,還有就是對於後端服務的主要實現進行講解。
微服務閘道器已經基本介紹完了閘道器的實現,包括服務路由、幾種過濾方式等。這一節將重點介紹實際應用時的整合。對於需要修改增強的地方如下:
繪製的流程圖如下:
閘道器路由流程圖
對外暴露的介面可以直接訪問,這可以依賴配置檔案,而配置檔案又可以通過配置中心進行動態更新,所以不用擔心有hard-code的問題。
在配置檔案中定義需要permitall的路徑。
auth:permitall:
pattern: /login/**
pattern: /web/public/**
服務啟動時,讀入相應的configuration,下面的配置屬性讀取以auth開頭的配置。
@bean@configurationproperties(prefix = "auth")
public permitallurlproperties getpermitallurlproperties() catch (exception e) else )
@retention(retentionpolicy.runtime)
@inherited
@documented
public @inte***ce preauth {
string value();
target用於描述註解的使用範圍,超出範圍時編譯失敗,可以用在方法或者類上面。在執行時生效。不了解註解相關知識的,可以自行google。
@component@aspect
public class authaspect {
@pointcut("@annotation(com.blueskykong.auth.demo.annotation.preauth)")
private void cut() {
* 定製乙個環繞通知,當想獲得註解裡面的屬性,可以直接注入該註解
* @param joinpoint
* @param preauth
@around("cut()&&@annotation(preauth)")
public object record(proceedingjoinpoint joinpoint, preauth preauth) throws throwable {
//取出註解中的表示式
string value = preauth.value();
//spring el 對value進行解析
securityexpressionoperations operations = new customersecurityexpressionroot(securitycontextholder.getcontext().getauthentication());
standardevaluationcontext operationcontext = new standardevaluationcontext(operations);
expressionparser parser = new spelexpressionparser();
expression expression = parser.parseexpression(value);
//獲取表示式判斷的結果
boolean result = expression.getvalue(operationcontext, boolean.class);
if (result) {
//繼續執行介面內的方法
return joinpoint.proceed();
return "forbidden";
因為aspect作用在bean上,所以先用component把這個類新增到容器中。@pointcut
定義要攔截的註解。@around
定製乙個環繞通知,當想獲得註解裡面的屬性,可以直接注入該註解。切面表示式內主要實現了,利用spring el對value進行解析,將securitycontextholder.getcontext()
轉換成標準的操作上下文,然後解析註解中的表示式,最後獲取對表示式判斷的結果。
public customersecurityexpressionroot(authentication authentication) {
super(authentication);
customersecurityexpressionroot
繼承的是抽象類securityexpressionroot
,而我們用到的實際表示式是定義在securityexpressionoperations
介面,securityexpressionroot
又實現了securityexpressionoperations
介面。不過這裡面的具體判斷實現,spring security 呼叫的也是spring el。
下面我們看看最終介面是怎麼用上面實現的註解。
@preauth("hasauthority('create_company')") // 還可以定義很多表示式,如hasrole('admin')public string test() {
return "ok";
@preauth
中,可以定義的表示式很多,可以看securityexpressionoperations
介面中的方法。目前筆者只是實現了hasauthority()
表示式,如果你想支援其他所有表示式,只需要構造相應的securitycontextholder
即可。
有些讀者看了上面的設計,既然好多用到了spring security的工具類,肯定會問,為什麼要引入這麼複雜的工具類?
其實很簡單,首先因為securityexpressionoperations
介面中定義的表示式足夠多,且較為合理,能夠覆蓋我們在平時用到的大部分場景;其次,筆者之前的設計是直接在註解中指定所需許可權,沒有擴充套件性,且可讀性差;最後,spring security 4 確實引入了@preauthorize,@postauthorize
等註解,本來想用來著,自己嘗試了一下,發現對於微服務架構這樣的介面級別的操作許可權校驗不是很適合,十多個過濾器太過複雜,而且還涉及到的principal、credentials等資訊,這些已經在auth系統實現了身份合法性校驗。筆者認為這邊的功能實現並不是很複雜,需要很輕量的實現,讀者有興趣可以試著這部分的實現封裝成jar包或者spring boot的starter。
優化的地方主要有兩點:
如上,首先講了整合的設計思路,主要包含三個服務:gateway、auth和backend demo。整合的專案,總體比較複雜,其中gateway服務擴充了好多內容,對於暴露的介面進行路由**,這邊引入了spring security 的starter,配置資源伺服器對暴露的路徑進行放行;對於其他介面需要呼叫auth服務進行身份合法性校驗,保證到達backend的請求都是合法的或者公開的介面;auth服務在之前的基礎上,補充了role、permission、user相應的介面,供外部呼叫;backend demo是新起的服務,實現了介面級別的操作許可權的校驗,主要用到了自定義註解和spring aop切面。
由於實現的細節實在有點多,本文限於篇幅,只對部分重要的實現進行列出與講解。如果讀者有興趣實際的應用,可以根據實際的業務進行擴增一些資訊,如auth授權的token、閘道器攔截請求構造的頭部資訊、註解支援的表示式等等。
可以優化的地方當然還有很多,整合專案中設計不合理的地方,各位同學可以多多提意見。
推薦閱讀
系列文章:認證鑑權與api許可權控制在微服務架構中的設計與實現 原始碼
閘道器、auth許可權服務和backend服務的整合專案位址為:
github:
或者 碼雲:
微服務架構之 API閘道器
在微服務架構的系列文章中,前面已經通過文章 架構設計之 服務註冊 介紹過了服務註冊的原理和應用,今天這篇文章我們來聊一聊 api閘道器 api閘道器 是任何微服務架構的重要組成部分。有了它我們可以在乙個獨立的模組上方便的處理一些非業務邏輯,可以讓微服務本身專注在自身特定的功能上,使得每個微服務的開發...
微服務架構 BFF和閘道器
bff backend for frontend 和閘道器gateway是微服務架構中的兩個重要概念,這兩個概念相對比較新,有些開發人員甚至是架構師都不甚理解。本文用假想的公司案例 圖示的方式,解釋bff和閘道器是什麼,它們是怎麼演化出來的。希望對架構師設計和落地微服務架構有所啟發。我們先把時間推回...
微服務架構 去中心化的微服務閘道器
這篇文章主要還是想談如果僅僅是內部多個微服務模組間的介面服務整合,是否能夠實現一種去中心化的微服務閘道器,或者也可以理解為實現一種去中心化的輕量服務匯流排能力。要知道,在微服務模組間的介面服務呼叫中,涉及到安全,日誌,路由,監控,限流等能力,我們還是希望有乙個統一的微服務閘道器來處理。在前面的文章裡...