电竞比分网-中国电竞赛事及体育赛事平台

分享

最近在做 Spring Cloud 項目,松哥和大家分享一點微服務(wù)架構(gòu)中的安全管理思路

 鷹兔牛熊眼 2020-04-22
剛剛發(fā)表
查看:66666回復(fù):666

公眾號后臺回復(fù) ssm,免費獲取松哥純手敲的 SSM 框架學(xué)習(xí)干貨。

最近一段時間一直在發(fā)安全相關(guān)的 Spring Security 和 OAuth2,當(dāng)然這兩個系列還在繼續(xù),對 Spring Security 和 OAuth2 感興趣的小伙伴,不要錯過前面的文章哦,本文主要將一些理論上的東西,所以要是前面的 OAuth2 不懂,可能閱讀起來有些吃力:

「Spring Security 系列:」

  1. 挖一個大坑,Spring Security 開搞!
  2. 松哥手把手帶你入門 Spring Security,別再問密碼怎么解密了
  3. 手把手教你定制 Spring Security 中的表單登錄
  4. Spring Security 做前后端分離,咱就別做頁面跳轉(zhuǎn)了!統(tǒng)統(tǒng) JSON 交互
  5. Spring Security 中的授權(quán)操作原來這么簡單
  6. Spring Security 如何將用戶數(shù)據(jù)存入數(shù)據(jù)庫?
  7. Spring Security+Spring Data Jpa 強強聯(lián)手,安全管理只有更簡單!

「OAuth2 系列:」

  1. 做微服務(wù)繞不過的 OAuth2,松哥也來和大家扯一扯
  2. 這個案例寫出來,還怕跟面試官扯不明白 OAuth2 登錄流程?
  3. 死磕 OAuth2,教練我要學(xué)全套的!
  4. OAuth2 令牌還能存入 Redis ?越玩越溜!
  5. 想讓 OAuth2 和 JWT 在一起愉快玩耍?請看松哥的表演

這兩個系列都還沒完,還在繼續(xù)更新,也會定期推出文章的配套視頻,歡迎小伙伴們保持關(guān)注。

今天就不和大家聊代碼了,我想結(jié)合自己目前的工作,和大家說一說 Spring Cloud 基礎(chǔ)架構(gòu)的安全管理問題,因為我最近一直在做這方面的工作,有一些心得,發(fā)出來和小伙伴們一起探討。

這其實是一個挺復(fù)雜的問題,本文我盡量從一個容易理解的方面來和大家介紹,我們先把這個思想體系搭建起來,后面的文章,松哥會抽空給大家上代碼。

1.微服務(wù)架構(gòu)

在微服務(wù)中,我們一般都會有一個網(wǎng)關(guān),網(wǎng)關(guān)背后有很多個微服務(wù),所有的請求都是首先到達(dá)網(wǎng)關(guān),再由網(wǎng)關(guān)轉(zhuǎn)發(fā)到不同的服務(wù)上去。另外我們可能會搭建一個統(tǒng)一認(rèn)證中心,我畫一個已經(jīng)過簡化的架構(gòu)圖大家來看下:

可以看到,在這個微服務(wù)架構(gòu)中,我們的鑒權(quán)流程是這樣:

  1. 客戶端攜帶用戶名密碼發(fā)送登錄請求到網(wǎng)關(guān)。
  2. 網(wǎng)關(guān)收到請求之后,將請求路由到統(tǒng)一認(rèn)證中心。
  3. 統(tǒng)一認(rèn)證中心確認(rèn)用戶的身份沒有問題之后,將返回一個 access_token 給網(wǎng)關(guān)。
  4. 網(wǎng)關(guān)將 access_token 轉(zhuǎn)發(fā)到客戶端。
  5. 客戶端將獲取到的 access_token 放在請求頭中去請求真正的微服務(wù),當(dāng)然這個操作依然會被網(wǎng)關(guān)攔下。
  6. 網(wǎng)關(guān)將客戶端的請求路由到微服務(wù)上,接下來微服務(wù)需要根據(jù) access_token 鑒定用戶身份。
  7. 微服務(wù)可以調(diào)用統(tǒng)一認(rèn)證中心去檢驗用戶身份,如果我們采用了 JWT 的話,這一步實際上可以省略。
  8. 微服務(wù)確認(rèn)了用戶身份和權(quán)限之后,就可以根據(jù)實際情況返回數(shù)據(jù)給用戶了。

這是我們一個大致的認(rèn)證流程。

流程清楚了之后,代碼寫起來就非常容易了。有小伙伴會說,既然流程都清楚了,那我是不是可以自定義認(rèn)證的相關(guān)邏輯了?

這個想法沒錯,但是我并不建議。當(dāng)大家看到這張簡化版的架構(gòu)圖,應(yīng)該很容易就想到 OAuth2 了,很明顯,將 OAuth2 放在這里最恰當(dāng)不過。使用 OAuth2 好處是它是一個經(jīng)過市場驗證的安全標(biāo)準(zhǔn),使用 OAuth2 的話,你就不用擔(dān)心可能存在的風(fēng)險漏洞,如果是自己設(shè)計的話,要考慮的問題就比較多。

但是 OAuth2 中存在的一些角色問題在這里是如何劃分呢?

首先大家明白,OAuth2 中的授權(quán)服務(wù)器在校驗的時候,實際上是有兩個方面的校驗工作,一方面是校驗客戶端信息,另一方面是校驗用戶信息,微服務(wù) A 和 微服務(wù) B 都在處理業(yè)務(wù)上的事情,實際上沒有必要和客戶端關(guān)聯(lián)起來,所以我們可以在網(wǎng)關(guān)上先初步校驗客戶端信息,然后在微服務(wù)上再去校驗用戶身份信息。

具體來說是這樣:

在上面的架構(gòu)圖中,網(wǎng)關(guān)還有另外一個身份就是資源服務(wù)器,當(dāng)請求到達(dá)網(wǎng)關(guān)之后,如果是去往統(tǒng)一認(rèn)證中心的請求,則直接轉(zhuǎn)發(fā)即可;如果請求是去往普通微服務(wù)的請求,網(wǎng)關(guān)可以先做初步校驗,就是校驗客戶端身份,如果沒有問題,則將請求路由到不同的微服務(wù)上,各個微服務(wù)再根據(jù)自身的業(yè)務(wù)和權(quán)限情況,進(jìn)行響應(yīng)。

為什么不把所有權(quán)限校驗都在網(wǎng)關(guān)做了呢?

對于一個超大型的微服務(wù)項目而言,涉及到的子系統(tǒng)可能非常多,權(quán)限控制也是非常復(fù)雜,網(wǎng)關(guān)不可能了解所有業(yè)務(wù)系統(tǒng)的邏輯,如果把所有的鑒權(quán)操作都放在網(wǎng)關(guān)上做,很明顯會加大網(wǎng)關(guān)的復(fù)雜度,讓網(wǎng)關(guān)變得非常臃腫。另一方面,不同的微服務(wù)可能是由不同的團隊開發(fā)的,如果把每個微服務(wù)的鑒權(quán)系統(tǒng)放在網(wǎng)關(guān)上做,又會增加開發(fā)的難度,所以,我們可以先在網(wǎng)關(guān)對用戶身份做初步校驗,沒問題的話,再把請求路由到不同的微服務(wù),做具體的校驗。

在這個過程中,我們可以使用普通的 access_token,就是那種一個 UUID 字符串的,如果使用了這種格式的 access_token,我們可以通過調(diào)用授權(quán)服務(wù)器來確定用戶身份,也就是上圖中的第七步不可以省略,這對于分布式系統(tǒng)來說顯然不是最佳方案。結(jié)合 JWT 就可以很好的解決這個問題,JWT 中保存了用戶的所有信息,微服務(wù)拿到 JWT 字符串之后,就可以很好的解析出用戶的信息了。

2.為什么不建議 Cookie

微服務(wù)架構(gòu)是一種分布式系統(tǒng),在分布式系統(tǒng)中,我們經(jīng)常需要將用戶的信息從一個微服務(wù)傳遞到另外一個微服務(wù)中去,傳統(tǒng)的 SecurityContext 這種基于 ThreadLocal 基于內(nèi)存的方式顯然就不太合適,因為這種方式無法靈活的在分布式系統(tǒng)之間傳遞用戶信息,也無法很好的支持單點登錄。具體可以參考:想讓 OAuth2 和 JWT 在一起愉快玩耍?請看松哥的表演。

另一方面,前端應(yīng)用程序多樣化,Android、iOS、各種平臺的小程序、H5 頁面等等,并非所有的前端應(yīng)用都會對 Cookie 有友好的支持,后端使用 access_token 也可以避免前端將來面臨的這些問題。

3. 內(nèi)部調(diào)用鑒權(quán)

微服務(wù)內(nèi)部調(diào)用的鑒權(quán)也需要考慮。當(dāng)然,如果系統(tǒng)對于安全性的要求不高的話,這一步其實可以省略。

如果不能省略,我也來說說思路。

現(xiàn)在的微服務(wù)之間調(diào)用,例如 A 調(diào)用 B,如果是基于 Spring Cloud 架構(gòu)的話,可能以 Open Feign 調(diào)用為主,這種情況下,我們可以自定義一個請求攔截器,當(dāng)請求要發(fā)出的時候,自動攔截請求,然后自動向請求頭中添加認(rèn)證信息。

然后可以定義一個公共的注解,這個注解專門用來做校驗工作,該注解可以從從請求頭中提取出 A 傳遞來的信息進(jìn)行校驗。

在 B 中使用這個公共的注解即可。

當(dāng)然 B 中也可以不使用注解,而是通過路徑來校驗,但是在這個場景下,注解反而靈活一些。

4. 還要不要 Spring Security

有小伙伴會問,在微服務(wù)上拿到 JWT 字符串之后,是不是可以自己解析?(JWT 解析參考:Spring Security 結(jié)合 Jwt 實現(xiàn)無狀態(tài)登錄)這樣就不需要 Spring Security 了?

雖然自己解析并不存在技術(shù)上的難點,但是我還是不建議自己解析,建議繼續(xù)在 Spring Security 的基礎(chǔ)上完成剩余操作。

我們拿到 JWT 之后,通過 Spring Cloud Security 來自動解析 JWT 字符串,獲取用戶信息,然后自動將用戶信息注入 SecurityContext 中,相當(dāng)于自動完成一次登錄操作,然后繼續(xù)后面的操作,這樣自己要省事很多,而且 Spring Security 中的各種路徑攔截規(guī)則我們都還可以繼續(xù)使用。

好了,本文就是和大家聊一點思路,基于這個思路,松哥有一個 Spring Cloud 微服務(wù)腳手架代碼正在完善,近期會和小伙伴們見面,請大家保持關(guān)注哦~

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多