SpringCloud系列之網(wǎng)關(guān)gateway-11.權(quán)限認(rèn)證-分布式session替代方案

前面我們了解了Gateway組件的過(guò)濾器挚币,這一節(jié)我們就探討一下Gateway在分布式環(huán)境中的一個(gè)具體用例-用戶(hù)鑒權(quán)月帝。

傳統(tǒng)單應(yīng)用的用戶(hù)鑒權(quán)

從我們開(kāi)始學(xué)JavaEE的時(shí)候始赎,就被洗腦式灌輸了一種權(quán)限驗(yàn)證的標(biāo)準(zhǔn)做法矮台,那就是將用戶(hù)的登錄狀態(tài)保存到HttpSession中,比如在登錄成功后保存一對(duì)key-value值到session欲间,key是userId而value是用戶(hù)后臺(tái)的真實(shí)ID荤傲。接著創(chuàng)建一個(gè)ServletFilter過(guò)濾器耻涛,用來(lái)攔截需要登錄才能訪(fǎng)問(wèn)的資源呐伞,假如這個(gè)請(qǐng)求對(duì)應(yīng)的服務(wù)端session里找不到userId這個(gè)key,那么就代表用戶(hù)尚未登錄慎式,這時(shí)候可以直接拒絕服務(wù)然后重定向到用戶(hù)登錄頁(yè)面伶氢。
大家應(yīng)該都對(duì)session機(jī)制比較熟悉,它和cookie是相互依賴(lài)的瘪吏,cookie是存放在用戶(hù)瀏覽器中的信息癣防,而session則是存放在服務(wù)器端的。當(dāng)瀏覽器發(fā)起服務(wù)請(qǐng)求的時(shí)候就會(huì)帶上cookie掌眠,服務(wù)器端接到Request后根據(jù)cookie中的jsessionid拿到對(duì)應(yīng)的session蕾盯。
由于我們只啟動(dòng)一臺(tái)服務(wù)器,所以在登錄后保存的session始終都在這臺(tái)服務(wù)器中蓝丙,可以很方便的獲取到session中的所有信息级遭。用這野路子,我們一路搞定了各種課程作業(yè)和畢業(yè)設(shè)計(jì)渺尘。結(jié)果一到工作崗位發(fā)現(xiàn)行不通了挫鸽,因?yàn)樗袘?yīng)用都是集群部署,在一臺(tái)機(jī)器保存了的session無(wú)法同步到其他機(jī)器上鸥跟。那我們有什么成熟的解決方案嗎丢郊?
分布式環(huán)境下的解決方案

同步session

Session復(fù)制是最容易先想到的解決方案,我們可以把一臺(tái)機(jī)器中的session復(fù)制到集群中的其他機(jī)器医咨。比如Tomcat中也有內(nèi)置的session同步方案枫匾,但是這并不是一個(gè)很優(yōu)雅的解決方案,它會(huì)帶來(lái)以下兩個(gè)問(wèn)題:
? Timing問(wèn)題 同步需要花費(fèi)一定的時(shí)間拟淮,我們無(wú)法保證session同步的及時(shí)性干茉,也就是說(shuō),當(dāng)用戶(hù)發(fā)起的兩個(gè)請(qǐng)求分別落在不同機(jī)器上的時(shí)候惩歉,前一個(gè)請(qǐng)求寫(xiě)入session的信息可能還沒(méi)同步到所有機(jī)器等脂,后一個(gè)請(qǐng)求就已經(jīng)開(kāi)始執(zhí)行業(yè)務(wù)邏輯了俏蛮,這不免引起臟讀幻讀。
? 數(shù)據(jù)冗余 所有服務(wù)器都需要保存一份session全集上遥,這就產(chǎn)生了大量的冗余數(shù)據(jù)
反向代理:綁定IP或一致性Hash

這個(gè)方案可以放在Nignx網(wǎng)關(guān)層做的搏屑,我們可以指定某些IP段的請(qǐng)求落在某個(gè)指定機(jī)器上,這樣一來(lái)session始終只存在一臺(tái)機(jī)器上粉楚。不過(guò)相比前一種session復(fù)制的方法來(lái)說(shuō)辣恋,綁定IP的方式有更明顯的缺陷:
? 負(fù)載均衡 在綁定IP的情況下無(wú)法在網(wǎng)關(guān)層應(yīng)用負(fù)載均衡策略,而且某個(gè)服務(wù)器出現(xiàn)故障的話(huà)會(huì)對(duì)指定IP段的來(lái)訪(fǎng)用戶(hù)產(chǎn)生較大影響模软。對(duì)網(wǎng)關(guān)層來(lái)說(shuō)該方案的路由規(guī)則配置也極其麻煩伟骨。
? IP變更 很多網(wǎng)絡(luò)運(yùn)營(yíng)商會(huì)時(shí)不時(shí)切換用戶(hù)IP,這就會(huì)導(dǎo)致更換IP后的請(qǐng)求被路由到不同的服務(wù)節(jié)點(diǎn)處理燃异,這樣一來(lái)就讀不到前面設(shè)置的session信息了
為了解決第二個(gè)問(wèn)題携狭,可以通過(guò)一致性Hash的路由方案來(lái)做路由,比如根據(jù)用戶(hù)ID做Hash回俐,不同的Hash值落在不同的機(jī)器上逛腿,保證足夠均勻的分配,這樣也就避免了IP切換的問(wèn)題仅颇,但依然無(wú)法解決第一點(diǎn)里提到的負(fù)載均衡問(wèn)題单默。

Redis解決方案

這個(gè)方案解決了前面提到的大部分問(wèn)題,session不再保存在服務(wù)器上忘瓦,取而代之的是保存在redis中搁廓,所有的服務(wù)器都向redis寫(xiě)入/讀取緩存信息。
在Tomcat層面耕皮,我們可以直接引入tomcat-redis-session-manager組件境蜕,將容器層面的session組件替換為基于redis的組件,但是這種方案和容器綁定的比較緊密明场。另一個(gè)更優(yōu)雅的方案是借助spring-session管理redis中的session汽摹,盡管這個(gè)方案脫離了具體容器,但依然是基于Session的用戶(hù)鑒權(quán)方案苦锨,這類(lèi)Session方案已經(jīng)在微服務(wù)應(yīng)用中被淘汰了逼泣。
分布式Session的替代方案

To think out of box guys~讓我們把session拋到腦后,看看現(xiàn)在流行的兩種認(rèn)證方式:

OAuth 2.0

大家一定用過(guò)現(xiàn)在比較流行的第三方登錄舟舒,比如我們通過(guò)微信掃碼登錄就可以登錄某個(gè)應(yīng)用的在線(xiàn)系統(tǒng)拉庶,但是這個(gè)應(yīng)用并不知道我的微信用戶(hù)名和密碼。這便是我們要介紹的第一個(gè)鑒權(quán)方案-OAuth 2.0秃励。
OAuth 2.0是一個(gè)開(kāi)放授權(quán)標(biāo)準(zhǔn)協(xié)議氏仗,它允許用戶(hù)讓第三方應(yīng)用訪(fǎng)問(wèn)該用戶(hù)在某服務(wù)的特定私有資源,但是不提供賬號(hào)密碼信息給第三方應(yīng)用。在上面的例子中皆尔,微信就相當(dāng)于一個(gè)第三方應(yīng)用呐舔,我們通過(guò)OAuth 2.0

image.png

拿微信登錄第三方應(yīng)用的例子來(lái)說(shuō):
? Auth Grant 在這一步Client發(fā)起Authorization Request到微信系統(tǒng)(比如通過(guò)微信內(nèi)掃碼授權(quán)),當(dāng)身份驗(yàn)證成功后獲取Auth Grant
? Get Token 客戶(hù)端拿著從微信獲取到的Auth Grant慷蠕,發(fā)給第三方引用的鑒權(quán)服務(wù)珊拼,換取一個(gè)Token,這個(gè)Token就是訪(fǎng)問(wèn)第三方應(yīng)用資源所需要的令牌
? 訪(fǎng)問(wèn)資源 最后一步流炕,客戶(hù)端在請(qǐng)求資源的時(shí)候帶上Token令牌澎现,服務(wù)端驗(yàn)證令牌真實(shí)有效后即返回指定資源
我們可以借助Spring Cloud中內(nèi)置的
spring-cloud-starter-oauth2
組件搭建OAuth 2.0的鑒權(quán)服務(wù),OAuth 2.0的協(xié)議還涉及到很多復(fù)雜的規(guī)范每辟,比如角色剑辫、客戶(hù)端類(lèi)型、授權(quán)模式等渠欺。這一小節(jié)我們暫且不深入探討OAuth 2.0的實(shí)現(xiàn)方式妹蔽,先來(lái)看另外一個(gè)更輕量級(jí)的授權(quán)方案:JWT鑒權(quán)。

JWT鑒權(quán)

JWT也是一種基于Token的鑒權(quán)機(jī)制挠将,它的基本思想就是通過(guò)用戶(hù)名+密碼換取一個(gè)Access Token

鑒權(quán)流程

相比OAuth 2.0來(lái)說(shuō)讹开,它的鑒權(quán)過(guò)程更加簡(jiǎn)單,其基本流程是這樣的:

  1. 用戶(hù)名+密碼訪(fǎng)問(wèn)鑒權(quán)服務(wù)驗(yàn)證通過(guò):服務(wù)器返回一個(gè)Access Token給客戶(hù)端捐名,并將token保存在服務(wù)端某個(gè)地方用于后面的訪(fǎng)問(wèn)控制(可以保存在數(shù)據(jù)庫(kù)或者Redis中)
    a. 驗(yàn)證失敗:不生成Token
  2. 客戶(hù)端使用令牌訪(fǎng)問(wèn)資源闹击,服務(wù)器驗(yàn)證令牌有效性令牌錯(cuò)誤或過(guò)期:攔截請(qǐng)求镶蹋,讓客戶(hù)端重新申請(qǐng)令牌
    a. 令牌正確:允許放行

Access Token中的內(nèi)容

JWT的Access Token由三個(gè)部分構(gòu)成,分別是Header赏半、Payload和Signature贺归,我們分別看下這三個(gè)部分都包含了哪些信息:
? Header 頭部聲明了Token的類(lèi)型(JWT類(lèi)型)和采用的加密算法(HS256)
{'typ': 'JWT',
'alg': 'HS256'}
? Payload 這一段包含的信息相當(dāng)豐富,你可以定義Token簽發(fā)者断箫、簽發(fā)和過(guò)期時(shí)間拂酣、生效時(shí)間等一系列屬性,還可以添加自定義屬性仲义。服務(wù)端收到Token的時(shí)候也同樣可以對(duì)Payload中包含的信息做驗(yàn)證婶熬,比如說(shuō)某個(gè)Token的簽發(fā)者是“Feign-API”,假如某個(gè)接口只能允許“Gateway-API”簽發(fā)的Token埃撵,那么在做鑒權(quán)服務(wù)時(shí)就可以加入Issuer的判斷邏輯赵颅。
? Signature 它會(huì)使用Header和Payload以及一個(gè)密鑰用來(lái)生成簽證信息,這一步會(huì)使用Header里我們指定的加密算法進(jìn)行加密
目前實(shí)現(xiàn)JWT的開(kāi)源組件非常多暂刘,如果決定使用這個(gè)方案饺谬,只要添加任意一個(gè)開(kāi)源JWT實(shí)現(xiàn)的依賴(lài)項(xiàng)到項(xiàng)目中的pom文件,然后在加解密時(shí)調(diào)用該組件來(lái)完成谣拣。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末募寨,一起剝皮案震驚了整個(gè)濱河市族展,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拔鹰,老刑警劉巖仪缸,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異格郁,居然都是意外死亡腹殿,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)例书,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)锣尉,“玉大人,你說(shuō)我怎么就攤上這事决采∽圆祝” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵树瞭,是天一觀的道長(zhǎng)拇厢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)晒喷,這世上最難降的妖魔是什么孝偎? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮凉敲,結(jié)果婚禮上衣盾,老公的妹妹穿的比我還像新娘。我一直安慰自己爷抓,他們只是感情好势决,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蓝撇,像睡著了一般果复。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上渤昌,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天虽抄,我揣著相機(jī)與錄音,去河邊找鬼独柑。 笑死极颓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的群嗤。 我是一名探鬼主播菠隆,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了骇径?” 一聲冷哼從身側(cè)響起躯肌,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎破衔,沒(méi)想到半個(gè)月后清女,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晰筛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年嫡丙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片读第。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡曙博,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怜瞒,到底是詐尸還是另有隱情父泳,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布吴汪,位于F島的核電站惠窄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏漾橙。R本人自食惡果不足惜杆融,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望霜运。 院中可真熱鬧擒贸,春花似錦、人聲如沸觉渴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)案淋。三九已至,卻和暖如春险绘,著一層夾襖步出監(jiān)牢的瞬間踢京,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工宦棺, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瓣距,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓代咸,卻偏偏與公主長(zhǎng)得像蹈丸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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