2016-11-07 105 views
6

上下文:我正在創建一個雲平臺來支持具有SSO的多個應用程序。我正在使用Keycloak進行身份驗證Netflix Zuul授權(API網關)至Keycloak彈簧安全適配器微服務到微服務調用,來自隊列消息的授權

每個微服務都需要一個授權標頭,它包含一個有效的JWT,從中可以獲取用戶名(子)來處理請求。每個微服務到微服務的調用應首先通過Netflix Zuul,傳遞Authorization頭以維護無狀態驗證。該策略允許每個微服務都知道誰是間接調用微服務的用戶(子)。

問題1:如果從隊列消息中調用微服務,會發生什麼?我的一個想法是在隊列中存儲與消息+ userInfo相關的信息,並創建一個專用的微服務來處理這種消息,這種特殊的微服務應該從隊列中讀取userInfo並處理消息。

更新1:根據來自另一個論壇的電子郵件回覆,將JWT存儲在隊列中並不是一個好主意,因爲它可以輕鬆開採。

問題/問題2:但是,如果先前的特殊微服務要調用另一個正常的microService其期望接收JWT的頭會發生什麼?這個特殊的微服務應該由他自己創建一個JWT來模擬用戶並且能夠調用常規的微服務?

我想過的另一個解決方案是將原始JWT存儲在隊列中,但是如果稍後隊列調用特殊的微服務會發生什麼?在JWT不再有效之後(它已過期),被調用的微服務會拒絕請求?

可能的解決方案:(每若昂·安傑洛討論更新,見下文)

我應該從我的用戶(授權碼流)和我的服務(客戶端證書授予)驗證請求,這兩個請求應該包含有效負載中的用戶信息。當請求來自用戶時,我需要驗證有效載荷用戶信息是否與JWT聲明匹配。當請求來自服務時,我只需要信任該服務(只要它在我的控制之下)。

我會非常感謝您的幫助。謝謝。

回答

5

免責聲明:我從來沒有使用Keycloak,但標記wiki表示它符合OAuth2,所以我會信任這些信息。


在一個非常高的水平來看,你似乎有兩個要求:

  1. 驗證,而他使用的系統由最終用戶觸發的動作。
  2. 驗證您的系統在未知時間觸發的操作,以及最終用戶無需聯機的情況。

你已經遇到了第一個,依靠基於令牌的認證系統和我會做同樣的第二點上,唯一不同的是,該令牌將使用發給你的系統OAuth2客戶端憑據授予而不是針對有最終用戶的情況下的其他授權。

Client Credentials Grant

(來源:Client Credentials Grant

在你的情況,Keycloak將發揮Auth0的角色和你的客戶端應用程序可以保持使用自己的授權服務器進行身份驗證,並獲得客戶的祕密微服務訪問令牌。

一件事要有的一點是,如果你的系統依賴於sub要求比身份驗證和授權更多,那麼你可能需要做一些調整。例如,我已經看到系統執行操作A需要知道它是針對用戶X和Y的,但操作的有效負載僅接收用戶Y,並假定用戶X是當前通過身份驗證的主體。當所有內容都是同步的時候,這可以正常工作,但僅通過切換有效負載來指定兩個用戶都意味着該操作可以由系統認證的主體異步完成。

+0

HelloJoão,據我所知,1)微服務應該總是期望JWT來自用戶或其他服務。我只是做了測試,發現微服務的JWT與用戶相比的一些差異不包含聲明,並且它包含一個額外的「clientId」字段,因此,如果JWT包含「 clientId「不是用戶,而是服務。或者,我可以依賴「審計」字段,如果「審計」對應於客戶端名稱來驗證用戶,則它是用戶,如果不是,則是另一項服務。 –

+0

2)似乎我需要始終發送有效負載中的userId,以便服務可以以透明的方式處理請求(服務或用戶調用),如果我確定該調用來自用戶「aud」或「clientId」我可以使用「sub」或「preferred_username」來驗證有效載荷字段,以確保有效載荷的值與正在執行操作的用戶相對應。但是,在服務的情況下,我只需要信任有效負載中指定的用戶? –

+0

是的,這將是一種方法,驗證來自用戶的輸入,以確保他們不會假冒其他用戶並在來自您自己的服務時信任它。假設所有的微服務都在你的控制之下,這似乎是一個合適的方法。它也比存儲訪問令牌和/或刷新令牌似乎更簡單,以便您可以稍後執行呼叫,即使用戶處於脫機狀態。 –

0

一個常見的設置是有一個API gateway來驗證其JWT的所有傳入請求。 API網關驗證JWT的簽名(或對加密的JWT進行解密),檢查到期時間等,並從中提取範圍和用戶ID(子)。

然後它將範圍與每個micrto服務的一組定義範圍進行比較,如果範圍提供用戶(主題)訪問,則請求將轉發到微服務。用戶ID(JWT中的子用戶)以及存儲在JWT中的其他所需信息放置在自定義請求標題中,如X-IGNACIO-SUBJECT