純干貨!Spring Cloud Gateway整合OAuth2.0 實現(xiàn)分布式統(tǒng)一認(rèn)證授權(quán)

大家好,我是不才陳某~

今天這篇文章介紹一下Spring Cloud Gateway整合OAuth2.0實現(xiàn)認(rèn)證授權(quán)幻馁,涉及到的知識點有點多绞吁,有不清楚的可以看下陳某的往期文章哗脖。

文章目錄如下:

微服務(wù)認(rèn)證方案

微服務(wù)認(rèn)證方案目前有很多種糊肠,每個企業(yè)也是大不相同,但是總體分為兩類悯辙,如下:

網(wǎng)關(guān)只負(fù)責(zé)轉(zhuǎn)發(fā)請求琳省,認(rèn)證鑒權(quán)交給每個微服務(wù)商控制

統(tǒng)一在網(wǎng)關(guān)層面認(rèn)證鑒權(quán),微服務(wù)只負(fù)責(zé)業(yè)務(wù)

你們公司目前用的是哪種方案躲撰?

先來說說第一種方案针贬,有著很大的弊端,如下:

代碼耦合嚴(yán)重拢蛋,每個微服務(wù)都要維護一套認(rèn)證鑒權(quán)

無法做到統(tǒng)一認(rèn)證鑒權(quán)桦他,開發(fā)難度太大

第二種方案明顯是比較簡單的一種,優(yōu)點如下:

實現(xiàn)了統(tǒng)一的認(rèn)證鑒權(quán)谆棱,微服務(wù)只需要各司其職快压,專注于自身的業(yè)務(wù)

代碼耦合性低,方便后續(xù)的擴展

下面陳某就以第二種方案為例垃瞧,整合Spring Cloud Gateway+Spring Cloud Security?整合出一套統(tǒng)一認(rèn)證鑒權(quán)案例蔫劣。

案例架構(gòu)

開始擼代碼之前,先來說說大致的認(rèn)證鑒權(quán)流程个从,架構(gòu)如下圖:

大致分為四個角色脉幢,如下

客戶端:需要訪問微服務(wù)資源

網(wǎng)關(guān):負(fù)責(zé)轉(zhuǎn)發(fā)、認(rèn)證嗦锐、鑒權(quán)

OAuth2.0授權(quán)服務(wù):負(fù)責(zé)認(rèn)證授權(quán)頒發(fā)令牌

微服務(wù)集合:提供資源的一系列服務(wù)嫌松。

大致流程如下

1、客戶端發(fā)出請求給網(wǎng)關(guān)獲取令牌

2奕污、網(wǎng)關(guān)收到請求萎羔,直接轉(zhuǎn)發(fā)給授權(quán)服務(wù)

3、授權(quán)服務(wù)驗證用戶名菊值、密碼等一系列身份外驱,通過則頒發(fā)令牌給客戶端

4育灸、客戶端攜帶令牌請求資源腻窒,請求直接到了網(wǎng)關(guān)層

5昵宇、網(wǎng)關(guān)對令牌進行校驗(驗簽過期時間校驗....)儿子、鑒權(quán)(對當(dāng)前令牌攜帶的權(quán)限)和訪問資源所需的權(quán)限進行比對瓦哎,如果權(quán)限有交集則通過校驗,直接轉(zhuǎn)發(fā)給微服務(wù)

6柔逼、微服務(wù)進行邏輯處理

針對上述架構(gòu)需要新建三個服務(wù)蒋譬,分別如下:

名稱功能

oauth2-cloud-auth-serverOAuth2.0認(rèn)證授權(quán)服

oauth2-cloud-gateway網(wǎng)關(guān)服務(wù)

oauth2-cloud-order-service訂單資源服務(wù)

案例源碼目錄如下:

認(rèn)證授權(quán)服務(wù)搭建

很多企業(yè)是將認(rèn)證授權(quán)服務(wù)直接集成到網(wǎng)關(guān)中,這么做耦合性太高了愉适,這里陳某直接將認(rèn)證授權(quán)服務(wù)抽離出來犯助。

認(rèn)證服務(wù)的搭建這里就不再細(xì)說了,上一篇文章中已經(jīng)介紹的很清楚了:OAuth2.0實戰(zhàn)维咸!使用JWT令牌認(rèn)證剂买!

新建一個oauth2-cloud-auth-server模塊,目錄如下:

和上篇文章不同的是創(chuàng)建了

JwtTokenUserDetailsService這個類癌蓖,用于從數(shù)據(jù)庫中加載用戶瞬哼,如下:

為了演示只是模擬了從數(shù)據(jù)庫中查詢,其中存了兩個用戶租副,如下:

user:具有ROLE_user權(quán)限

admin:具有ROLE_admin坐慰、ROLE_user權(quán)限

要想這個生效,還要在security的配置文件SecurityConfig中指定用僧,如下圖:

另外還整合了注冊中心Nacos结胀,詳細(xì)配置就不貼了,可以看源碼责循。有不清楚Nacos糟港,可以看之前文章:五十五張圖告訴你微服務(wù)的靈魂擺渡者Nacos究竟有多強?

案例源碼已經(jīng)上傳GitHub沼死,關(guān)注公號:碼猿技術(shù)專欄着逐,回復(fù)關(guān)鍵詞:9529?獲取意蛀!

網(wǎng)關(guān)服務(wù)搭建

網(wǎng)關(guān)使用的是Spring Cloud Gateway耸别,網(wǎng)關(guān)如何搭建這里就不再細(xì)說了,有不清楚的可以看之前文章:Spring Cloud Gateway奪命連環(huán)10問县钥?

新建一個oauth2-cloud-gateway模塊秀姐,目錄如下圖:

1、添加依賴

需要添加幾個OAuth2.0相關(guān)的依賴若贮,如下:

2省有、JWT令牌服務(wù)配置

使用JWT令牌痒留,配置要和認(rèn)證服務(wù)的令牌配置相同,代碼如下:

3蠢沿、認(rèn)證管理器自定義

新建一個JwtAuthenticationManager伸头,需要實現(xiàn)

ReactiveAuthenticationManager這個接口。

認(rèn)證管理的作用就是獲取傳遞過來的令牌舷蟀,對其進行解析恤磷、驗簽過期時間判定野宜。

詳細(xì)代碼如下:

邏輯很簡單扫步,就是通過JWT令牌服務(wù)解析客戶端傳遞的令牌,并對其進行校驗匈子,比如上傳三處校驗失敗河胎,拋出令牌無效的異常。

拋出的異常如何處理虎敦?如何定制返回的結(jié)果游岳?

這里拋出的異常可以通過Spring Cloud Gateway的全局異常進行捕獲原茅,這個內(nèi)容在Spring Cloud Gateway奪命連環(huán)10問吭历?這篇文章有詳細(xì)的介紹。下面只貼出關(guān)鍵代碼擂橘,如下:

4晌区、鑒權(quán)管理器自定義

經(jīng)過認(rèn)證管理器JwtAuthenticationManager認(rèn)證成功后,就需要對令牌進行鑒權(quán)通贞,如果該令牌無訪問資源的權(quán)限朗若,則不允通過。

新建JwtAccessManager昌罩,實現(xiàn)

ReactiveAuthorizationManager哭懈,代碼如下:

這里的邏輯很簡單,就是取出令牌中的權(quán)限和當(dāng)前請求資源URI的權(quán)限對比茎用,如果有交集則通過遣总。

①處的代碼什么意思?

這里是直接從Redis中取出資源URI對應(yīng)的權(quán)限集合轨功,因此實際開發(fā)中需要維護資源URI和權(quán)限的對應(yīng)關(guān)系旭斥,這里不細(xì)說,為了演示古涧,陳某直接在項目啟動的時候向Redis中添加了兩個資源的權(quán)限垂券,代碼如下:

注意:實際開發(fā)中需要維護資源URI和權(quán)限的對應(yīng)關(guān)系。

②處的代碼什么意思羡滑?

這處代碼就是取出令牌中的權(quán)限集合

③處的代碼什么意思菇爪?

這處代碼就是比較兩者權(quán)限了算芯,有交集,則放行凳宙。

5熙揍、令牌無效或者過期時定制結(jié)果

在第4步,如果令牌失效或者過期近速,則會直接返回诈嘿,這里需要定制提示信息堪旧。

新建一個

RequestAuthenticationEntryPoint削葱,實現(xiàn)

ServerAuthenticationEntryPoint,代碼如下:

6淳梦、無權(quán)限時定制結(jié)果

在第4步鑒權(quán)的過程中析砸,如果無該權(quán)限,也是會直接返回爆袍,這里也需要定制提示信息首繁。

新建一個

RequestAccessDeniedHandler,實現(xiàn)ServerAccessDeniedHandler陨囊,代碼如下:

7弦疮、OAuth2.0相關(guān)配置

經(jīng)過上述6個步驟,相關(guān)組件已經(jīng)準(zhǔn)備就緒蜘醋,現(xiàn)在直接配置到OAuth2.0中胁塞。

新建SecurityConfig這個配置類,標(biāo)注注解?@EnableWebFluxSecurity压语,注意不是?@EnableWebSecurity啸罢,因為Spring Cloud Gateway是基于Flux實現(xiàn)的。詳細(xì)代碼如下:

需要配置的內(nèi)容如下:

認(rèn)證過濾器胎食,其中利用了認(rèn)證管理器對令牌進行校驗

鑒權(quán)管理器扰才、令牌失效異常處理、無權(quán)限訪問異常處理

白名單配置

跨域過濾器的配置

8厕怜、全局過濾器定制

試想一下:網(wǎng)關(guān)層面認(rèn)證鑒權(quán)成功后衩匣,下游微服務(wù)如何獲取到當(dāng)前用戶的詳細(xì)信息?

陳某這里是將令牌攜帶的用戶信息解析出來粥航,封裝成JSON數(shù)據(jù)琅捏,然后通過Base64加密,放入到請求頭中躁锡,轉(zhuǎn)發(fā)給下游微服務(wù)午绳。

這樣一來,下游微服務(wù)只需要解密請求頭中的JSON數(shù)據(jù)映之,即可獲取用戶的詳細(xì)信息拦焚。

因此需要在網(wǎng)關(guān)中定義一個全局過濾器蜡坊,用來攔截請求,解析令牌赎败,關(guān)鍵代碼如下:

上述代碼邏輯如下:

檢查是否是白名單秕衙,白名單直接放行

檢驗令牌是否存在

解析令牌中的用戶信息

封裝用戶信息到JSON數(shù)據(jù)中

加密JSON數(shù)據(jù)

將加密后的JSON數(shù)據(jù)放入到請求頭中

好了,經(jīng)過上述8個步驟僵刮,完整的網(wǎng)關(guān)已經(jīng)搭建成功了据忘。

訂單微服務(wù)搭建

由于在網(wǎng)關(guān)層面已經(jīng)做了鑒權(quán)了(細(xì)化到每個URI),因此微服務(wù)就不用集成Spring Security單獨做權(quán)限控制了搞糕。

因此這里的微服務(wù)也是相對比較簡單了勇吊,只需要將網(wǎng)關(guān)層傳遞的加密用戶信息解密出來,放入到Request中窍仰,這樣微服務(wù)就能隨時獲取到用戶的信息了汉规。

新建一個

oauth2-cloud-order-service模塊,目錄如下:

新建一個過濾器AuthenticationFilter驹吮,用于解密網(wǎng)關(guān)傳遞的用戶數(shù)據(jù)针史,代碼如下:

新建兩個接口,返回當(dāng)前登錄的用戶信息碟狞,如下:

注意:以上兩個接口所需要的權(quán)限已經(jīng)放入到了Redis中啄枕,權(quán)限如下:

/order/login/info:ROLE_admin和ROLE_user都能訪問

/order/login/admin:ROLE_admin權(quán)限才能訪問

案例源碼已經(jīng)上傳GitHub,關(guān)注公號:碼猿技術(shù)專欄族沃,回復(fù)關(guān)鍵詞:9529?獲绕底!!

為什么要將URI和權(quán)限放入Redis竭业?

在網(wǎng)關(guān)的鑒權(quán)管理器那里是直接從Redis中獲取URI對應(yīng)的權(quán)限智润,然后和令牌中的權(quán)限比較,為什么要這樣做未辆?

這也是目前企業(yè)中比較常用的一種方式窟绷,將鑒權(quán)完全放在了網(wǎng)關(guān)層面,也實現(xiàn)了動態(tài)權(quán)限校驗咐柜。當(dāng)然有些是直接將接口的權(quán)限控制在每個微服務(wù)中兼蜈。

采用陳某的這種方案需要另外維護URI和權(quán)限的對應(yīng)關(guān)系,當(dāng)然這種難度很低拙友,便于實現(xiàn)为狸。

只是一種方案,具體是否選用還要考慮到架構(gòu)層面遗契。

測試

同時啟動上述三個服務(wù)辐棒,如下:

1、用密碼模式登錄user,獲取令牌漾根,如下

2泰涂、使用user用戶的令牌訪問/order/login/info接口,如下

可以看到成功返回了辐怕,因為具備ROLE_user權(quán)限逼蒙。

3、使用user用戶的令牌訪問/order/login/admin接口寄疏,如下

可以看到直接返回了無權(quán)限訪問是牢,直接在網(wǎng)關(guān)層被攔截了。

總結(jié)

本篇文章只是簡單的整合了網(wǎng)關(guān)+OAuth2.0陕截,實際開發(fā)中還有一些細(xì)節(jié)待完善驳棱,由于文章篇幅限制,后續(xù)介紹......

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末艘策,一起剝皮案震驚了整個濱河市蹈胡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌朋蔫,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件却汉,死亡現(xiàn)場離奇詭異驯妄,居然都是意外死亡,警方通過查閱死者的電腦和手機合砂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門青扔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人翩伪,你說我怎么就攤上這事微猖。” “怎么了缘屹?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵凛剥,是天一觀的道長。 經(jīng)常有香客問我轻姿,道長犁珠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任互亮,我火速辦了婚禮犁享,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘豹休。我一直安慰自己炊昆,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凤巨,像睡著了一般屏积。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上磅甩,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天炊林,我揣著相機與錄音,去河邊找鬼卷要。 笑死渣聚,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的僧叉。 我是一名探鬼主播奕枝,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瓶堕!你這毒婦竟也來了隘道?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤郎笆,失蹤者是張志新(化名)和其女友劉穎谭梗,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宛蚓,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡激捏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凄吏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片远舅。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖痕钢,靈堂內(nèi)的尸體忽然破棺而出图柏,到底是詐尸還是另有隱情,我是刑警寧澤任连,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布蚤吹,位于F島的核電站,受9級特大地震影響课梳,放射性物質(zhì)發(fā)生泄漏距辆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一暮刃、第九天 我趴在偏房一處隱蔽的房頂上張望跨算。 院中可真熱鬧,春花似錦椭懊、人聲如沸诸蚕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽背犯。三九已至坏瘩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間漠魏,已是汗流浹背倔矾。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留柱锹,地道東北人哪自。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像禁熏,于是被迫代替她去往敵國和親壤巷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容