隨著計(jì)算機(jī)、互聯(lián)網(wǎng)技術(shù)的飛速發(fā)展,信息安全已然是一個(gè)全民關(guān)心的問題,也是各大企業(yè)非常重視的問題。企業(yè)一般會(huì)從多個(gè)層次著手保障信息安全,如:物理安全、網(wǎng)絡(luò)安全、系統(tǒng)安全(主機(jī)和操作系統(tǒng))、應(yīng)用安全等。

對(duì)于應(yīng)用程序安全,需要在應(yīng)用架構(gòu)、代碼、運(yùn)維、管理等多個(gè)角度進(jìn)行安全性評(píng)估,在整個(gè)應(yīng)用程序生命周期中,軟件工程師們則主要負(fù)責(zé)身份驗(yàn)證、訪問授權(quán)、進(jìn)程間通信安全、代碼安全、安全的管理與審計(jì)這五方面的方案落地。這五個(gè)方面中,前三個(gè)側(cè)重于技術(shù)實(shí)現(xiàn),代碼安全、管理與審計(jì)則更需要規(guī)范的管理和執(zhí)行,本文將著重對(duì)認(rèn)證、授權(quán)、通信等技術(shù)相關(guān)內(nèi)容重點(diǎn)介紹,管理規(guī)范相關(guān)內(nèi)容僅做簡(jiǎn)單說明。
文中以采用了微服務(wù)架構(gòu)的應(yīng)用程序?yàn)楸尘斑M(jìn)行描述,但多數(shù)的應(yīng)用程序的安全方案與是否采用微服務(wù)架構(gòu)并沒有強(qiáng)關(guān)聯(lián),如有差異的地方,文中會(huì)提出來。文中描述過程中會(huì)涉及到一些微服務(wù)架構(gòu)中相關(guān)的概念名詞,說明如下:

微服務(wù)架構(gòu)中安全訪問相關(guān)的簡(jiǎn)化版的運(yùn)行視圖如下:

運(yùn)行視圖
圖中星號(hào)*標(biāo)注的位置就是服務(wù)調(diào)用過程中安全訪問過程中的一些需要認(rèn)證鑒權(quán)的關(guān)鍵位置,如:內(nèi)外部訪問認(rèn)證、令牌驗(yàn)證與授權(quán)、內(nèi)外網(wǎng)通信協(xié)議等。后續(xù)章節(jié)將對(duì)這部分展開分析。
1.身份認(rèn)證
多數(shù)業(yè)務(wù)功能類的應(yīng)用的首要任務(wù)就是需要做身份認(rèn)證。對(duì)于數(shù)據(jù)公開或新聞發(fā)布類的門戶網(wǎng)站類應(yīng)用不需要考慮這一點(diǎn),他們更關(guān)注的是數(shù)據(jù)開放之前的管理和審批。
身份認(rèn)證或身份驗(yàn)證(Authentication),顧名思義就是對(duì)應(yīng)用程序的"訪問者"的身份進(jìn)行驗(yàn)證識(shí)別。訪問者分兩類。
基于用戶登錄的客戶端(Login-based Client):用戶訪問服務(wù)提供者的應(yīng)用程序的功能時(shí),需要通過一個(gè)客戶端交互界面來與服務(wù)提供者交互,用戶需要先登錄,然后由客戶端代表用戶身份去訪問服務(wù)提供者應(yīng)用程序。
API 客戶端(API Client):客戶端程序類型的訪問者,這類客戶端自身具備部分API的訪問權(quán)限,不需要用戶授予其訪問權(quán)限。
1. 使用認(rèn)證管理系統(tǒng)IAM進(jìn)行訪問者注冊(cè)認(rèn)證
不論是用戶還是API客戶端,在訪問應(yīng)用之前,均需要先到認(rèn)證管理系統(tǒng)IAM進(jìn)行注冊(cè),以創(chuàng)建其的身份憑證(用戶賬號(hào)和密碼、客戶端ID和密碼)。有了身份憑證,才能通過認(rèn)證服務(wù)的驗(yàn)證。
統(tǒng)一認(rèn)證管理系統(tǒng)IAM(Identity and Access Management )負(fù)責(zé)身份識(shí)別和訪問管理,其核心業(yè)務(wù)是應(yīng)用系統(tǒng)的訪問者的注冊(cè)、賬號(hào)密碼憑證、訪問者基本信息的管理、對(duì)已注冊(cè)的訪問者進(jìn)行合法性認(rèn)證和訪問的初級(jí)授權(quán)(獲取訪問者自身數(shù)據(jù))等等。
有些企業(yè)還會(huì)將組織機(jī)構(gòu)、角色甚至業(yè)務(wù)功能權(quán)限數(shù)據(jù)也一并歸入IAM系統(tǒng)管理。IAM對(duì)權(quán)限管理范圍可大可小,不同企業(yè)的管理需求和力度也不一樣,需要集中進(jìn)行功能授權(quán)管理還是下放到業(yè)務(wù)系統(tǒng)中自治各有優(yōu)缺點(diǎn),選擇合適自己的方式就好。
2. IAM認(rèn)證管理系統(tǒng)使用OAuth2.0進(jìn)行訪問者授權(quán)
傳統(tǒng)WEB應(yīng)用對(duì)于用戶登錄訪問,采用會(huì)話狀態(tài)在服務(wù)端保存的方案,用戶請(qǐng)求通常采用會(huì)話粘滯(Sticky session)或會(huì)話復(fù)制(Replication session)策略,來保持客戶端和服務(wù)端的會(huì)話。為了會(huì)話共享而不得不將會(huì)話信息寫入公共緩存或數(shù)據(jù)庫(kù),導(dǎo)致微服務(wù)應(yīng)用之間產(chǎn)生了耦合性。
微服務(wù)架構(gòu)中不推薦采用服務(wù)端保存會(huì)話的方式,如果引入狀態(tài)管理不是必要的,那么應(yīng)用盡量保持無狀態(tài)運(yùn)行。推薦使用另外一種基于訪問令牌的模式,這種模式下應(yīng)用中不需要保存會(huì)話狀態(tài),并且API客戶端和基于登錄的客戶端均方便使用訪問令牌。微服務(wù)架構(gòu)推薦使用OAuth2.0 授權(quán)協(xié)議來搭建IAM系統(tǒng)。Spring 體系可以基于Spring Security OAuth實(shí)現(xiàn)授權(quán)服務(wù)器和客戶端。
在本文的上下文中,面向的是企業(yè)基于微服務(wù)的總體架構(gòu)進(jìn)行方案設(shè)計(jì),企業(yè)整體架構(gòu)中,默認(rèn)認(rèn)證體系方案為企業(yè)統(tǒng)一認(rèn)證而非業(yè)務(wù)系統(tǒng)各自認(rèn)證(此方案的前提條件)。OAuth2.0本身是為三方授權(quán)而設(shè)計(jì)的,而在本方案中討論的是企業(yè)內(nèi)部應(yīng)用的整體認(rèn)證和授權(quán),不存在第三方。因此本方案中基于OAuth2.0實(shí)現(xiàn)的授權(quán)服務(wù)可以簡(jiǎn)單理解為僅為IAM統(tǒng)一認(rèn)證管理系統(tǒng)中的“賬號(hào)管理應(yīng)用資源提供者”做授權(quán),并且默認(rèn)實(shí)現(xiàn)為認(rèn)證通過自動(dòng)授予已登錄賬號(hào)數(shù)據(jù)的讀寫權(quán)限,不在登錄通過后與用戶交互確認(rèn)是否同意授權(quán)。其他業(yè)務(wù)系統(tǒng)作為資源提供者的授權(quán)則是系統(tǒng)管理員預(yù)置好的授權(quán),也不需要由用戶登錄時(shí)決定是否授權(quán)。這個(gè)OAuth2.0的使用場(chǎng)景可能與其他OAuth2.0相關(guān)資料或授權(quán)框架默認(rèn)實(shí)現(xiàn)有所不同,請(qǐng)大家注意區(qū)分。
OAuth協(xié)議中定義了四種角色:
能夠許可對(duì)受保護(hù)資源的訪問權(quán)限的實(shí)體。當(dāng)資源所有者是個(gè)人時(shí),它被稱為最終用戶。
托管受保護(hù)資源的服務(wù)器,能夠接收和響應(yīng)使用訪問令牌對(duì)受保護(hù)資源的請(qǐng)求。
使用資源所有者的授權(quán)代表資源所有者發(fā)起對(duì)受保護(hù)資源的請(qǐng)求的應(yīng)用程序。術(shù)語“客戶端”并非特指任何特定的的實(shí)現(xiàn)特點(diǎn)(例如:應(yīng)用程序是否是在服務(wù)器、臺(tái)式機(jī)或其他設(shè)備上執(zhí)行)。
在成功驗(yàn)證資源所有者且獲得授權(quán)后頒發(fā)訪問令牌給客戶端的服務(wù)器。
角色分析:
對(duì)于前面提到的API 客戶端,自身具備API訪問權(quán),不需要用戶授權(quán),因此在OAuth角色對(duì)應(yīng)時(shí),它既是客戶端又是資源所有者。
微服務(wù)架構(gòu)中Web應(yīng)用一般采用前后端分離的模式,前端為基于瀏覽器訪問的純前端應(yīng)用,網(wǎng)關(guān)作為應(yīng)用程序的入口,此時(shí)網(wǎng)關(guān)本身可以代表OAuth中的客戶端身份訪問服務(wù)提供端應(yīng)用的功能接口。
在微服務(wù)架構(gòu)中,負(fù)責(zé)頒發(fā)訪問令牌的授權(quán)服務(wù)通常在IAM系統(tǒng)中實(shí)現(xiàn)
資源服務(wù)器,在微服務(wù)架構(gòu)中,所有的業(yè)務(wù)系統(tǒng)中的服務(wù)功能提供者都是資源服務(wù)器,也包括IAM系統(tǒng)的賬號(hào)、組織機(jī)構(gòu)服務(wù)、資源權(quán)限管理服務(wù)等等
在OAuth2.0授權(quán)協(xié)議中,主要定義了四種許可類型:授權(quán)碼許可、簡(jiǎn)單許可、密碼憑據(jù)許可和客戶端憑據(jù)許可,詳細(xì)請(qǐng)參見規(guī)范內(nèi)容:rfc6749 - The OAuth 2.0 Authorization Framework
(https://tools.ietf.org/html/rfc6749)
下面我們根據(jù)訪問者類型,分別推薦合適的授權(quán)方案。
2.1 API客戶端作為訪問者,使用客戶端憑證許可
典型的API客戶端如批量調(diào)度系統(tǒng)、物聯(lián)網(wǎng)設(shè)備程序等,通常不需要用戶登錄授權(quán)就可以自動(dòng)運(yùn)行。使用客戶端憑證許可類型比較適合。

客戶端憑證
上圖為OAuth2.0規(guī)范標(biāo)準(zhǔn)流程圖,結(jié)合此場(chǎng)景中,對(duì)應(yīng)OAuth2.0中的角色,API客戶端作為OAuth2.0的客戶端、IAM則為授權(quán)服務(wù)器。
(A) API客戶端與授權(quán)服務(wù)器IAM進(jìn)行身份驗(yàn)證并請(qǐng)求訪問令牌。
(B) 授權(quán)服務(wù)器IAM對(duì)API客戶端進(jìn)行身份驗(yàn)證,如果有效,頒發(fā)訪問令牌。客戶端存儲(chǔ)訪問令牌,在后 續(xù)的請(qǐng)求過程中使用。如果令牌過期或失效或需要重復(fù)此流程再次申請(qǐng)?jiān)L問令牌。
其他說明:
此類應(yīng)用通常不具備與用戶交互的UI,無需用戶授權(quán),具備保證客戶端憑證安全的能力
此類應(yīng)用后端需要具備通過https訪問授權(quán)服務(wù)器的能力
此類應(yīng)用或設(shè)備需要具備存儲(chǔ)Access Token的能力
2.2 基于登錄的客戶端作為訪問者,使用授權(quán)碼許可
2.2.1 Web 應(yīng)用
OAuth2.0 協(xié)議中提出前端單頁Web應(yīng)用可以用簡(jiǎn)單許可模式,但簡(jiǎn)單許可模式有些局限性,令牌到期就需要重新登錄授權(quán),不支持令牌刷新,用戶體驗(yàn)較差。很多使用簡(jiǎn)單授權(quán)的應(yīng)用為了改善用戶體驗(yàn)會(huì)頒發(fā)一個(gè)長(zhǎng)期的令牌幾天甚至幾周。
如果有條件使用授權(quán)碼模式,支持刷新令牌則是一個(gè)更好的選擇。對(duì)訪問令牌時(shí)間較短如2分鐘,刷新令牌為一次性令牌有效期略長(zhǎng)如30分,如果存在已作廢的刷新令牌換取訪問令牌的請(qǐng)求,授權(quán)端點(diǎn)也能夠及時(shí)發(fā)現(xiàn)做出相應(yīng)入侵處理,如注銷該用戶的所有刷新令牌。在保持良好用戶體驗(yàn)的同時(shí)還兼顧了部分安全性。
本場(chǎng)景以微服務(wù)架構(gòu)中常見的前后端分離Web應(yīng)用作為示例,前端是單頁應(yīng)用,網(wǎng)關(guān)作為Web后臺(tái)是服務(wù)提供端應(yīng)用功能入口,也可作為OAuth2.0的客戶端,讓前端Web應(yīng)用能借助網(wǎng)關(guān)實(shí)現(xiàn)授權(quán)碼交換。因此在微服務(wù)架構(gòu)中,即便是純前端單頁應(yīng)用類的Web應(yīng)用,仍可以用基于網(wǎng)關(guān)交互的授權(quán)碼模式獲取訪問令牌。其他非前后端分離的混合Web應(yīng)用自身就是客戶端,不需要借助網(wǎng)關(guān)交換訪問令牌。

授權(quán)碼
上圖為OAuth2.0規(guī)范標(biāo)準(zhǔn)流程圖,結(jié)合此場(chǎng)景對(duì)應(yīng)OAuth2.0中的角色,用戶是資源所有者、瀏覽器為用戶代理、網(wǎng)關(guān)作為被授權(quán)的客戶端、IAM則為授權(quán)服務(wù)器。
(A) 網(wǎng)關(guān)通過引導(dǎo)瀏覽器開始流程授權(quán)流程,重定向到統(tǒng)一認(rèn)證中心的登錄頁面。
(B)用戶輸入密碼登錄,授權(quán)服務(wù)器驗(yàn)證用戶身份,并確認(rèn)用戶是否授權(quán)網(wǎng)關(guān)的訪問請(qǐng)求。
(C)用戶授權(quán)后,認(rèn)證中心根據(jù)之前網(wǎng)關(guān)注冊(cè)時(shí)提供的回調(diào)地址,引導(dǎo)瀏覽器重定向回到網(wǎng)關(guān)。重定向URI包含授權(quán)碼
(D)網(wǎng)關(guān)通過包含上一步中收到的授權(quán)碼和網(wǎng)關(guān)自身憑證從授權(quán)服務(wù)器IAM的請(qǐng)求訪問令牌。
(E)授權(quán)服務(wù)器IAM對(duì)網(wǎng)關(guān)進(jìn)行身份驗(yàn)證,驗(yàn)證授權(quán)代碼,并確保接收的重定向URI與網(wǎng)關(guān)注冊(cè)時(shí)的URI相匹配。匹配成功后,授權(quán)服務(wù)器IAM響應(yīng)返回訪問令牌與可選的刷新令牌給網(wǎng)關(guān)。
其他說明:
為了前端會(huì)話保持,訪問令牌由網(wǎng)關(guān)在響應(yīng)時(shí)返回到前端,存儲(chǔ)到前端存儲(chǔ)空間,如Cookie、Local Storage、Session Storage等。
訪問令牌失效后,網(wǎng)關(guān)根據(jù)自己的客戶端憑證+刷新令牌一起發(fā)送授權(quán)服務(wù)器,獲取新的訪問令牌和刷新令牌,并再返回響應(yīng)中將訪問令牌寫入到用戶瀏覽器的存儲(chǔ)中。
授權(quán)碼模式中,用戶的憑證(用戶名、密碼)是用戶通過瀏覽器與授權(quán)服務(wù)交互,并不經(jīng)過網(wǎng)關(guān), 安全性最好。
2.2.2 移動(dòng)App
個(gè)人移動(dòng)設(shè)備上安裝的原生App本身具備實(shí)現(xiàn)授權(quán)碼流程的能力,不需要借助網(wǎng)關(guān)實(shí)現(xiàn)授權(quán)碼流程。認(rèn)證通過后網(wǎng)關(guān)僅負(fù)責(zé)校驗(yàn)訪問令牌即可。

授權(quán)碼
移動(dòng)App實(shí)現(xiàn)登錄重定向通?梢圆捎萌缦路绞剑
移動(dòng)端App的運(yùn)行環(huán)境是不可信的,容易被惡意App入侵的風(fēng)險(xiǎn),包含如下兩種情況:
重定向過程中的回調(diào)URL參數(shù),容易被惡意App占用URL Scheme或者監(jiān)聽localhost端口截取。
運(yùn)行環(huán)境不可靠,移動(dòng)App不具備安全保存客戶端秘鑰的能力,而使用授權(quán)碼獲取訪問令牌時(shí)需要校驗(yàn)客戶端秘鑰。
基于上述風(fēng)險(xiǎn)和問題,移動(dòng)App基于授權(quán)碼獲取訪問令牌的流程需要進(jìn)行優(yōu)化解決,rfc規(guī)范中建議的實(shí)現(xiàn)方案是移動(dòng)App授權(quán)流程采用使用帶有PKCE支持的授權(quán)碼模式。PKCE, 全稱Proof Key for Code Exchange,即保護(hù)授權(quán)代碼授權(quán)。這其實(shí)是通過一種密碼學(xué)手段確保惡意第三方即使截獲Authorization Code或者其他密鑰,也無法向認(rèn)證服務(wù)器交換Access Token。
經(jīng)過PKCE改進(jìn)的授權(quán)碼、訪問令牌交換過程示意圖如下:

PKCE
上圖為PKCE模式下授權(quán)碼申請(qǐng)和交換訪問令牌的過程,說明如下:
(A) 移動(dòng)App客戶端創(chuàng)建并保存名為code_verifier的隨機(jī)秘鑰串,并將秘鑰字符串加密轉(zhuǎn)換的結(jié)果t(code_verifier)稱為code_challenge,將轉(zhuǎn)換后的code_challenge以及轉(zhuǎn)換方法一并發(fā)送到授權(quán)服務(wù)中。
(B) 授權(quán)服務(wù)返回授權(quán)碼并記錄code_challenge和轉(zhuǎn)換方法t_m。
(C) 移動(dòng)App客戶端收到授權(quán)碼后,將授權(quán)碼和code_verifier秘鑰串發(fā)送到授權(quán)服務(wù)器,用以申請(qǐng)?jiān)L問令牌。
(D) 授權(quán)服務(wù)器根據(jù)轉(zhuǎn)換方法t_m 轉(zhuǎn)換code_verifier 并與步驟A中收到的code_challenge比較,如果一致則返回訪問令牌,否則拒絕非法請(qǐng)求。
第三方無法根據(jù)code_challenge推導(dǎo)出code_verifier,因?yàn)閏ode_challenge采用了不可逆加密方式。只有移動(dòng)App客戶端自己才知道這兩個(gè)值。因此即使惡意App截獲了code_challenge和授權(quán)碼,也無法換取訪問令牌避免了安全問題。要實(shí)現(xiàn)這種移動(dòng)App的PKCE授權(quán)碼模式,出移動(dòng)App自身外,還需要IAM的授權(quán)服務(wù)器基于標(biāo)準(zhǔn)的授權(quán)碼流程擴(kuò)展配合實(shí)現(xiàn)。
關(guān)于移動(dòng)App安全認(rèn)證的詳細(xì)內(nèi)容請(qǐng)參考官方規(guī)范:
(https://tools.ietf.org/html/rfc825)
(https://tools.ietf.org/html/rfc7636)
2.3 高度信任的特權(quán)類客戶端,可以使用資源所有者密碼憑據(jù)許可

用戶密碼憑據(jù)
上圖為OAuth2.0規(guī)范標(biāo)準(zhǔn)流程圖,結(jié)合此場(chǎng)景中,對(duì)應(yīng)OAuth2.0中的角色,用戶是資源擁有者、特權(quán)應(yīng)用是客戶端、IAM提供授權(quán)服務(wù)器
(A)用戶提供給特權(quán)App用戶名和密碼。
(B)特權(quán)App將用戶憑據(jù)提交給授權(quán)服務(wù)器IAM,申請(qǐng)?jiān)L問令牌
(C)授權(quán)服務(wù)器IAM 驗(yàn)證用戶的憑證,如果有效,頒發(fā)訪問令牌給特權(quán)App。特權(quán)App對(duì)授權(quán)服務(wù)器頒發(fā)的訪問令牌、刷新令牌進(jìn)行存儲(chǔ)和更新。
其他說明:
3. 使用API 網(wǎng)關(guān)作業(yè)務(wù)系統(tǒng)訪問入口,負(fù)責(zé)驗(yàn)證訪問令牌
訪問者能夠訪問的接口通常是兩類:身份認(rèn)證API、應(yīng)用功能類API。
身份認(rèn)證類API:即登錄認(rèn)證相關(guān)的API。為了避免用戶、客戶端憑證泄漏第三方(除IAM、訪問者之外為第三方),身份認(rèn)證類API或UI建議由IAM系統(tǒng)直接開放給訪問者調(diào)用進(jìn)行身份認(rèn)證。
應(yīng)用功能類API:功能實(shí)現(xiàn)來自服務(wù)提供者,通過網(wǎng)關(guān)開放給訪問者。網(wǎng)關(guān)是訪問應(yīng)用API的入口。
用戶登錄認(rèn)證由IAM授權(quán)服務(wù)器配合用戶資源服務(wù)負(fù)責(zé)。認(rèn)證成功后,IAM訪問者頒發(fā)訪問令牌。后續(xù)對(duì)應(yīng)用功能的訪問過程中,均須攜帶訪問令牌以表明訪問者的身份。
3.1 由網(wǎng)關(guān)負(fù)責(zé)客戶端身份驗(yàn)證
網(wǎng)關(guān)作為業(yè)務(wù)系統(tǒng)的API入口,當(dāng)面向外網(wǎng)的訪問者時(shí)網(wǎng)關(guān)還是內(nèi)外網(wǎng)的分界,訪問令牌驗(yàn)證理應(yīng)由網(wǎng)關(guān)負(fù)責(zé),不應(yīng)該將令牌驗(yàn)證的事情交給服務(wù)提供者。網(wǎng)關(guān)負(fù)責(zé)驗(yàn)證既能避免未經(jīng)驗(yàn)證的請(qǐng)求進(jìn)入內(nèi)網(wǎng),又能夠簡(jiǎn)化服務(wù)提供端的代碼,服務(wù)提供端無需處理不同類型客戶端的驗(yàn)證。實(shí)際上好處還不只這些,在網(wǎng)關(guān)可以統(tǒng)一做流控?zé)o需應(yīng)用端重復(fù)建設(shè)類似功能;系統(tǒng)內(nèi)部調(diào)試、變更敏捷,減少了跨組織交互。
網(wǎng)關(guān)驗(yàn)證訪問令牌有兩種方案:網(wǎng)關(guān)委托認(rèn)證服務(wù)驗(yàn)證、網(wǎng)關(guān)直接驗(yàn)證,說明如下:

網(wǎng)關(guān)委托IAM校驗(yàn)令牌
客戶端成功認(rèn)證后,使用UUID類型的訪問令牌調(diào)用網(wǎng)關(guān)上的服務(wù)
由于UUID類型令牌不包含客戶端的信息,網(wǎng)關(guān)需要委托IAM認(rèn)證服務(wù)校驗(yàn)令牌
令牌檢查合法后,將請(qǐng)求路由到服務(wù)提供者
應(yīng)用中也無法解析令牌,需要根據(jù)UUID令牌到IAM中獲取用戶信息

網(wǎng)關(guān)直接校驗(yàn)令牌
客戶端成功認(rèn)證后,使用JWT令牌調(diào)用網(wǎng)關(guān)上的服務(wù)
網(wǎng)關(guān)自己直接解密JWT令牌進(jìn)行校驗(yàn)
令牌檢查合法后,將請(qǐng)求路由到服務(wù)提供者
應(yīng)用受到請(qǐng)求后,如果需要更多權(quán)限信息,如果可以根據(jù)Token去權(quán)限管理服務(wù)獲取權(quán)限信息(非必須步驟,需要時(shí)添加)。
上述兩方案中,方案一的令牌是無業(yè)務(wù)含義的身份標(biāo)識(shí)字符串,每次收到請(qǐng)求網(wǎng)關(guān)都去IAM認(rèn)證,對(duì)IAM認(rèn)證服務(wù)的性能壓力較大。方案二中IAM頒發(fā)的令牌中包含部分客戶端或用戶信息,使用JWT加密,IAM將驗(yàn)證方式或SDK提供給了負(fù)責(zé)認(rèn)證的網(wǎng)關(guān)。對(duì)于IAM來說,減少了每次請(qǐng)求令牌認(rèn)證帶來的通信次數(shù),減輕了IAM的壓力。
推薦采用方案二實(shí)現(xiàn)令牌檢查,需要注意的是方案二中的JWT令牌中僅包含必要的信息即可,不要放太多的角色權(quán)限信息。后續(xù)功能中需要額外的信息時(shí),可以根據(jù)令牌再去IAM中獲取。如果令牌中存放了很多的權(quán)限數(shù)據(jù),一旦后臺(tái)的授權(quán)數(shù)據(jù)發(fā)生變化,令牌中的權(quán)限數(shù)據(jù)與實(shí)際IAM的權(quán)限會(huì)存在不一致的問題,只能強(qiáng)制用戶下線重新登錄。
JWT令牌是防篡改的,但并不加密,如需要存儲(chǔ)到瀏覽器存儲(chǔ)中,建議采用JWT+JWE方式進(jìn)行令牌加密。令牌中存放必要少量數(shù)據(jù)即可,避免濫用。多數(shù)服務(wù)器通常會(huì)對(duì)Http header、cookie長(zhǎng)度做限制。
3.2 系統(tǒng)內(nèi)部應(yīng)用是否通過網(wǎng)關(guān)?
我的答案是不需要,否則太麻煩了。通常網(wǎng)關(guān)是獨(dú)立團(tuán)隊(duì)負(fù)責(zé),API變更發(fā)布、內(nèi)部聯(lián)調(diào)驗(yàn)證還得跨團(tuán)隊(duì)協(xié)調(diào)實(shí)在不可行。推薦系統(tǒng)內(nèi)直通不走網(wǎng)關(guān),系統(tǒng)之間訪問必須走網(wǎng)關(guān)。要做到這一點(diǎn),應(yīng)用也需要實(shí)別請(qǐng)求來源進(jìn)行客戶端認(rèn)證,這種認(rèn)證方案沒必要太復(fù)雜,應(yīng)用只應(yīng)該允許信任的網(wǎng)關(guān)和系統(tǒng)內(nèi)部應(yīng)用程序訪問其服務(wù),不允許系統(tǒng)外部請(qǐng)求繞過網(wǎng)關(guān)直接調(diào)用,因此,需要在網(wǎng)關(guān)和系統(tǒng)內(nèi)部應(yīng)用之間這個(gè)小范圍內(nèi)建立信任,常見方案有兩種:
方案一,內(nèi)部令牌:系統(tǒng)內(nèi)的應(yīng)用在發(fā)布接口到網(wǎng)關(guān)時(shí),提供一個(gè)系統(tǒng)內(nèi)部共享的令牌給網(wǎng)關(guān)和系統(tǒng)內(nèi)所有應(yīng)用,接收到請(qǐng)求時(shí)檢查請(qǐng)求頭中是否包含系統(tǒng)內(nèi)信任的令牌, 如果包含可信任令牌,那么就允許訪問,否則就拒絕
方案二,系統(tǒng)內(nèi)保密令牌+網(wǎng)關(guān)證書單獨(dú)認(rèn)證:系統(tǒng)內(nèi)用保密令牌交互就是方案一,只是內(nèi)部令牌不共享給網(wǎng)關(guān),網(wǎng)關(guān)用公私鑰證書簽名方式與域內(nèi)系統(tǒng)建立信任,由網(wǎng)關(guān)生成公私鑰證書,頒發(fā)公鑰給各個(gè)系統(tǒng),網(wǎng)關(guān)調(diào)用服務(wù)提供者時(shí),請(qǐng)求頭中帶上用私鑰簽名的令牌,應(yīng)用收到請(qǐng)求以后用網(wǎng)關(guān)發(fā)布的公鑰驗(yàn)證其令牌。
方案一優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單,缺點(diǎn)是安全級(jí)別略低,常見的企業(yè)架構(gòu)中,網(wǎng)關(guān)和業(yè)務(wù)系統(tǒng)會(huì)是不同團(tuán)隊(duì)甚至不同的廠商負(fù)責(zé)開發(fā)維護(hù),內(nèi)部令牌共享給了其他團(tuán)隊(duì)負(fù)責(zé)的網(wǎng)關(guān),存在一定的風(fēng)險(xiǎn)。方案二相比方案一略復(fù)雜一點(diǎn),安全性更高,系統(tǒng)內(nèi)互通用內(nèi)部令牌,系統(tǒng)和網(wǎng)關(guān)認(rèn)證使用了網(wǎng)關(guān)提供的安全令牌檢查方式。兩種方案可根據(jù)實(shí)際需求選擇。
2.訪問授權(quán)
通過認(rèn)證的API客戶端能夠訪問網(wǎng)關(guān)開發(fā)的所有API嗎?通過認(rèn)證的用戶能夠調(diào)用所有API嗎?通過認(rèn)證的用戶允許調(diào)用修改訂單的接口,那么他能修改所有人的訂單嗎?
很顯然絕大多數(shù)場(chǎng)景下上述三個(gè)問題答案都是"不能"。在絕大多數(shù)業(yè)務(wù)場(chǎng)景中除了對(duì)訪問者的身份認(rèn)證之外,我們還需要再進(jìn)一步控制權(quán)限。
1. API客戶端訪問網(wǎng)關(guān)接口時(shí),網(wǎng)關(guān)需進(jìn)行API權(quán)限控制
如果訪問者是API客戶端時(shí),API調(diào)用的權(quán)限需由網(wǎng)關(guān)進(jìn)行控制。建議采用先訂閱再訪問的授權(quán)模式,網(wǎng)關(guān)應(yīng)該僅允許API客戶端訪問其訂閱過的API 。具體實(shí)現(xiàn)方法就是絕大多數(shù)網(wǎng)關(guān)都會(huì)提供的基于API Key控制API訪問的方式。
需要注意的是,僅使用API key的訪問控制是不夠的。API Key是在網(wǎng)關(guān)訂閱API時(shí)生成的一串唯一編號(hào),并不具備識(shí)別客戶端身份的能力。就好比以前買火車票是不實(shí)名的,誰拿到火車票,都可以乘坐對(duì)應(yīng)車次;疖嚻睂(shí)名制之后,首先需要核驗(yàn)身份證,核驗(yàn)通過后才能購(gòu)票乘車。如果證票不符,則不允許乘車。
將客戶端認(rèn)證和API Key配合進(jìn)行訪問認(rèn)證和權(quán)限校驗(yàn)才是個(gè)更安全的方案。

API權(quán)限控制
上圖為訪問令牌結(jié)合API Key的認(rèn)證鑒權(quán)示意圖,說明如下:
客戶端1獲取了API Key 但其沒有合法的訪問令牌,如果不允許匿名訪問,則網(wǎng)關(guān)會(huì)拒絕客戶端1訪問,返回錯(cuò)誤碼401表示客戶端未通過認(rèn)證;
客戶端2擁有了合法的訪問令牌,但其API Key不合法,網(wǎng)關(guān)在客戶端2認(rèn)證檢查通過后,檢查API Key,發(fā)現(xiàn)其權(quán)限不足,則返回錯(cuò)誤碼403表示客戶端的權(quán)限不足;
客戶端3擁有合法的客戶端訪問令牌和API Key訪問網(wǎng)關(guān)上的服務(wù),網(wǎng)關(guān)認(rèn)證、鑒權(quán)通過之后,將請(qǐng)求路由到實(shí)際的服務(wù)提供端,最終發(fā)回正常響應(yīng)數(shù)據(jù)。
2. 用戶訪問應(yīng)用功能時(shí)需要進(jìn)行權(quán)限控制
用戶訪問的功能權(quán)限或數(shù)據(jù)權(quán)限不要交給網(wǎng)關(guān)管控,原因是網(wǎng)關(guān)僅能支持API Path授權(quán),而實(shí)際需要控制的用戶權(quán)限有很多,如菜單、API、數(shù)據(jù)等。如果由網(wǎng)關(guān)控制用戶權(quán)限,管少了不滿足需求,管多了就要耦合太多應(yīng)用數(shù)據(jù)。
因此推薦用戶權(quán)限由業(yè)務(wù)系統(tǒng)自行管理維護(hù)和控制。每個(gè)業(yè)務(wù)系統(tǒng)內(nèi)部如果需要控制用戶權(quán)限,可以建設(shè)一個(gè)基礎(chǔ)權(quán)限框架,負(fù)責(zé)管理權(quán)限數(shù)據(jù),并提供訪問請(qǐng)求攔截和權(quán)限檢查的SDK給其他應(yīng)用。
也有部分企業(yè)權(quán)限管理要求較高,將系統(tǒng)內(nèi)部的基礎(chǔ)權(quán)限框架抽取為獨(dú)立的權(quán)限管理服務(wù),由獨(dú)立團(tuán)隊(duì)維護(hù)該服務(wù),采用分布式部署+權(quán)限緩存的方式保障性能。這樣做的好處是權(quán)限模型統(tǒng)一、容易對(duì)權(quán)限變更進(jìn)行審批控制和審計(jì)。缺點(diǎn)是跨團(tuán)隊(duì)交互,變更流程復(fù)雜。
關(guān)于權(quán)限管理,是業(yè)務(wù)系統(tǒng)自治或是集中管控,根據(jù)企業(yè)自身的需求特點(diǎn)決定即可。
3.通信安全
通信安全的方案就是基于傳輸過程加密的方式,常見的選擇就是使用Https協(xié)議通信。
微服務(wù)架構(gòu)體系中,邏輯層面上外部請(qǐng)求接入都是通過網(wǎng)關(guān)作為入口,網(wǎng)關(guān)作為內(nèi)外網(wǎng)的分界,實(shí)際部署上,網(wǎng)關(guān)本身也是多實(shí)例分布式的高可用部署形態(tài),前面架設(shè)有一個(gè)負(fù)載均衡F5或nginx,用來對(duì)外提供Https協(xié)議接入和路由轉(zhuǎn)發(fā),而網(wǎng)關(guān)內(nèi)部就是企業(yè)內(nèi)網(wǎng),默認(rèn)是可信任的,內(nèi)網(wǎng)的系統(tǒng)之間的通信會(huì)采用更輕量級(jí)的HTTP協(xié)議。此方案中微服務(wù)換成SOA,把網(wǎng)關(guān)換成ESB,就是傳統(tǒng)的SOA架構(gòu)中的安全通信方案,本質(zhì)上沒有區(qū)別。
示意圖如下:

內(nèi)外網(wǎng)通信協(xié)議
為什么用了https就能保證通信安全呢?https是http+ssl,采用密碼學(xué)手段對(duì)通信報(bào)文做了加密,使得報(bào)文無法被篡改,做到了安全傳輸,從而保障了通信安全。關(guān)于https原理和負(fù)載均衡器證書配置相關(guān)資料網(wǎng)絡(luò)上有很多,請(qǐng)大家即用即查。
4.代碼安全
敏感配置加密:上述各種服務(wù)安全場(chǎng)景和方案聊了那么多,大家發(fā)現(xiàn)保存好令牌、密鑰、密碼是一切安全的前提。這些東西千萬不能外泄。要保證密碼不泄露的辦法就是做好敏感數(shù)據(jù)保密,技術(shù)手段上則要求存儲(chǔ)密碼、憑證的地方(配置文件和數(shù)據(jù)庫(kù)表)需要加密存儲(chǔ)。如:配置文件中的數(shù)據(jù)庫(kù)口令、數(shù)據(jù)表中存放的密碼數(shù)據(jù)等
代碼質(zhì)量管理:建議在開發(fā)期對(duì)于編碼規(guī)范進(jìn)行制定,還可以通過工具進(jìn)行輔助檢查和控制,如開源的代碼質(zhì)量管理工具Sonar,可以支持多種程序語言,方便的與編譯構(gòu)建工具集成如Maven,在代碼進(jìn)入正式提交對(duì)應(yīng)分支前就將一些安全問題在前期預(yù)防,如SQL注入等。
運(yùn)行時(shí)安全掃描:測(cè)試階段,可以通過安全掃描軟件,如AppScan 等工具對(duì)業(yè)務(wù)系統(tǒng)的前后端功能進(jìn)行掃描,檢查系統(tǒng)漏洞并即時(shí)修復(fù)。盡量減小在上線運(yùn)行后出現(xiàn)安全事故的風(fēng)險(xiǎn)。
5.管理審計(jì)
運(yùn)維管理安全方面,根據(jù)安全需求,要有安全相關(guān)的管理規(guī)范和工具支撐,對(duì)系統(tǒng)管理、權(quán)限分配和關(guān)鍵數(shù)據(jù)進(jìn)行嚴(yán)格管控,并做好操作審計(jì)日志記錄。
比如很多安全級(jí)別高的行業(yè)或企業(yè)中如軍工類,對(duì)于業(yè)務(wù)系統(tǒng)的修改、權(quán)限管理審計(jì)做了嚴(yán)格的流程規(guī)范和功能支撐。如典型的三員管理,采用三權(quán)分立、互相制約的思路,包含系統(tǒng)管理員、安全管理員、安全審計(jì)員三個(gè)角色,互相能看到對(duì)方的信息,將業(yè)務(wù)過程分成不同的段,每段由對(duì)應(yīng)人員負(fù)責(zé),不讓任何人掌控全局。
審計(jì)工作是非常重要的一環(huán),沒有任何系統(tǒng)和流程是絕對(duì)安全的。關(guān)鍵的操作、數(shù)據(jù)變化等審計(jì)日志需要完整記錄。一旦發(fā)生問題,可以通過審計(jì)日志排查分析追蹤。常見內(nèi)容舉例如下:
對(duì)于敏感數(shù)據(jù)項(xiàng)(如:密碼)的訪問
客戶端注冊(cè)、用戶認(rèn)證授權(quán)過程
權(quán)限的授予和廢除
關(guān)鍵數(shù)據(jù)的變更、刪除
審計(jì)功能的啟動(dòng)和關(guān)閉
其他關(guān)鍵API、命令的訪問
以上這些審計(jì)方面的工作中,如果是基于API相關(guān)的審計(jì)信息記錄,如邊界交互報(bào)文數(shù)據(jù),建議基于統(tǒng)一的技術(shù)框架進(jìn)行記錄管理。一些內(nèi)部實(shí)現(xiàn)方法,則可以采用接口、方法上加注解,AOP攔截后記錄的方案。其他情況可根據(jù)實(shí)際需求設(shè)計(jì)審計(jì)數(shù)據(jù)存儲(chǔ)的方案。