您好,登錄后才能下訂單哦!
今天小編給大家分享一下如何實(shí)現(xiàn)微服務(wù)鑒權(quán)的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。
首先小伙伴們知道,無(wú)論我們學(xué)習(xí) Shiro 還是 Spring Security,里邊的功能無(wú)論有哪些,核心都是兩個(gè):
認(rèn)證
授權(quán)
所以,我們?cè)谖⒎?wù)中處理鑒權(quán)問(wèn)題,也可以從這兩個(gè)方面來(lái)考慮。
認(rèn)證,說(shuō)白了就是登錄。傳統(tǒng)的 Web 登錄是 Cookie+Session 的方案,這種方案依賴于服務(wù)器本地內(nèi)存,在微服務(wù)中,由于服務(wù)眾多,這種方案顯然不再合適。
可能會(huì)有小伙伴說(shuō)用 Redis+SpringSession 做 Session 共享,這是個(gè)辦法,但是不是最佳方案,因?yàn)檫@種方案的性能以及可擴(kuò)展性都比較差。
所以,微服務(wù)中的認(rèn)證,還是建議使用令牌的方式,可以選擇 JWT 令牌,這也是目前使用較多的一種方案。但是熟悉 JWT 的小伙伴都知道,純粹的無(wú)狀態(tài)登錄無(wú)法實(shí)現(xiàn)注銷(xiāo),這就很頭大,所以在實(shí)際應(yīng)用中,單純的使用 JWT 是不行的,一般還是要結(jié)合 Redis 一起,將生成的 JWT 字符串在 Redis 上也保存一份,并設(shè)置過(guò)期時(shí)間,判斷用戶是否登錄時(shí),需要先去 Redis 上查看 JWT 字符串是否存在,存在的話再對(duì) JWT 字符串做解析操作,如果能成功解析,就沒(méi)問(wèn)題,如果不能成功解析,就說(shuō)明令牌不合法。
這樣有狀態(tài)登錄+無(wú)狀態(tài)登錄混在一起的方式,雖然看起來(lái)有點(diǎn)不倫不類(lèi),但是就當(dāng)下來(lái)說(shuō),這個(gè)折衷的辦法算是一個(gè)可行的方案了。
其實(shí),上面的方案,說(shuō)白了,跟傳統(tǒng)的 Cookie+Session 沒(méi)什么兩樣,思路幾乎都是完全 copy 的:傳統(tǒng)的 Session 用 Redis 代替了;傳統(tǒng)穿梭于服務(wù)端和瀏覽器之間的 jsessionId 被 JWT 字符串代替了;傳統(tǒng)的 jsessionId 通過(guò) Cookie 來(lái)傳輸,現(xiàn)在的 JWT 則通過(guò)開(kāi)發(fā)者手動(dòng)設(shè)置后通過(guò)請(qǐng)求頭來(lái)傳輸;傳統(tǒng)的 Session 可以自動(dòng)續(xù)簽,現(xiàn)在用 JWT 就是手動(dòng)續(xù)簽,每次請(qǐng)求到達(dá)服務(wù)端的時(shí)候,就去看下 Redis 上令牌的過(guò)期時(shí)間,快過(guò)期了,就重新設(shè)置一下,其他都一模一樣。
這是認(rèn)證方案的選擇。
微服務(wù)中授權(quán),也可以使用 Shiro 或者 Spring Security 框架來(lái)做,省事一些??紤]到微服務(wù)技術(shù)棧都是 Spring 家族的產(chǎn)品,所以在權(quán)限框架這塊也是建議大家首選 Spring Security(如果有小伙伴對(duì) Spring Security 還不熟悉的話,可以在微信公眾號(hào)后臺(tái)回復(fù) ss,有教程)。
當(dāng)然,如果覺(jué)得 Spring Security 比較復(fù)雜想自己搞的話,也是可以的。自己搞的話,也是可以借助于 Spring Security 的思路的,松哥最近的一個(gè)項(xiàng)目就是這樣:
請(qǐng)求到達(dá)微服務(wù)之后,先找到當(dāng)前用戶的各種信息,包括當(dāng)前用戶所擁有的角色和權(quán)限等信息,然后存入到和當(dāng)前線程綁定的 ThreadLocal 對(duì)象中。另一方面自定義權(quán)限注解和角色注解,在切面中對(duì)這些注解進(jìn)行解析,檢查當(dāng)前用戶是否具備所需要的角色/權(quán)限等。
當(dāng)然,如果你使用了 Spring Security 的話,上面這個(gè)就不需要自定義注解了,直接使用 Spring Security 中自帶的即可,還可以體驗(yàn) Spring Security 中更多的豐富的安全功能。
那么認(rèn)證和授權(quán)在哪里做?
先來(lái)說(shuō)認(rèn)證,認(rèn)證我們可以簡(jiǎn)單分為兩個(gè)步驟:
登錄
校驗(yàn)
一般來(lái)說(shuō),登錄我們可以單獨(dú)做一個(gè)認(rèn)證服務(wù)。當(dāng)?shù)卿浾?qǐng)求到達(dá)網(wǎng)關(guān)之后,我們將之轉(zhuǎn)發(fā)到認(rèn)證服務(wù)上,完成認(rèn)證操作。
在認(rèn)證服務(wù)上,我們就去檢查用戶名/密碼是否 OK,用戶狀態(tài)是否都 OK,都沒(méi)問(wèn)題的話,生成 JWT 字符串,同時(shí)再把數(shù)據(jù)存入到 Redis 上,然后把 JWT 字符串返回。
如果系統(tǒng)有注冊(cè)功能的話,注冊(cè)功能也是放在這個(gè)微服務(wù)上來(lái)完成。
校驗(yàn)是指每一個(gè)請(qǐng)求到達(dá)的時(shí)候,校驗(yàn)用戶是否已經(jīng)登錄。
這個(gè)當(dāng)然可以和 2.1 放到一起去做,但是松哥不建議。問(wèn)題在于,假如是一個(gè)創(chuàng)建訂單的請(qǐng)求,這個(gè)請(qǐng)求原本是要經(jīng)過(guò)網(wǎng)關(guān)轉(zhuǎn)發(fā)到訂單服務(wù)上的,但是,此時(shí)就得先在網(wǎng)關(guān)上調(diào)用 2.1 小節(jié)的服務(wù)進(jìn)行登錄校驗(yàn),沒(méi)問(wèn)題再轉(zhuǎn)發(fā)到訂單服務(wù)上,這樣做很明顯很費(fèi)事,也不合理。
一個(gè)比較好的辦法是直接在網(wǎng)關(guān)上去校驗(yàn)請(qǐng)求的令牌是否合法,這個(gè)校驗(yàn)本身也比較容易,校驗(yàn)令牌是否合法,我們只需要看 Redis 上是否存在這個(gè)令牌,并且這個(gè) JWT 令牌能夠被順利解析就行,這個(gè)操作完全可以在網(wǎng)關(guān)上做。
以 Gateway 網(wǎng)關(guān)為例,我們可以自定義全局過(guò)濾器,在全局過(guò)濾器中校驗(yàn)每一個(gè)請(qǐng)求的令牌,校驗(yàn)通過(guò)了,再進(jìn)行請(qǐng)求的轉(zhuǎn)發(fā),否則就不轉(zhuǎn)發(fā)。
校驗(yàn)通過(guò)之后,在轉(zhuǎn)發(fā)到具體的微服務(wù)之后,我們可以將解析出來(lái)的用戶 id 以及用戶名等信息放到請(qǐng)求頭中,然后再轉(zhuǎn)發(fā),這樣到達(dá)各個(gè)具體的微服務(wù)之后,就知道這個(gè)請(qǐng)求是誰(shuí)發(fā)來(lái)的,這人都有哪些角色/權(quán)限,方便做下一步的權(quán)限校驗(yàn)。
松哥的做法是定義了一個(gè)公共模塊,所有的微服務(wù)都依賴這個(gè)公共模塊,這個(gè)公共模塊中定義了一個(gè)攔截器,會(huì)攔截下來(lái)每一個(gè)請(qǐng)求,從請(qǐng)求頭中取出用戶 ID,然后從 Redis 中拿到具體的用戶信息,存入到 ThreadLocal 中,這樣在后續(xù)的方法調(diào)用中,如果需要判斷用戶是否具備某一個(gè)權(quán)限,就可以通過(guò) ThreadLocal 去獲取了。
大致上就是這樣一個(gè)流程。
授權(quán)沒(méi)法放到網(wǎng)關(guān)上做,還是得在各個(gè)微服務(wù)上去完成。
微服務(wù)上的授權(quán)我們又可以將之大致上分為兩類(lèi):
前端發(fā)送來(lái)的請(qǐng)求(外部請(qǐng)求)。
別的微服務(wù)發(fā)送來(lái)的請(qǐng)求(內(nèi)部請(qǐng)求)。
對(duì)于外部請(qǐng)求來(lái)說(shuō),就按正常的權(quán)限校驗(yàn)對(duì)待就行了,自定義注解亦或者使用 Spring Security 等框架都是可以的,如果是自定義注解的話,就結(jié)合 AOP 一起,定義切面自己去處理權(quán)限注解,當(dāng)然,這些功能基本上每一個(gè)微服務(wù)都是需要的,所以可以將之抽取成為一個(gè)公共的模塊,在不同的微服務(wù)中依賴即可。
對(duì)于內(nèi)部的請(qǐng)求來(lái)說(shuō),正常是不需要鑒權(quán)的,內(nèi)部請(qǐng)求可以直接處理。問(wèn)題是如果使用了 OpenFeign,數(shù)據(jù)都是通過(guò)接口暴露出去的,不鑒權(quán)的話,又會(huì)擔(dān)心從外部來(lái)的請(qǐng)求調(diào)用這個(gè)接口,對(duì)于這個(gè)問(wèn)題,我們也可以自定義注解+AOP,然后在內(nèi)部請(qǐng)求調(diào)用的時(shí)候,額外加一個(gè)頭字段加以區(qū)分。
當(dāng)然,內(nèi)部請(qǐng)求到達(dá)微服務(wù)的時(shí)候,也是需要進(jìn)行認(rèn)證的,就行請(qǐng)求從網(wǎng)關(guān)轉(zhuǎn)發(fā)到每一個(gè)具體的微服務(wù)上時(shí)需要認(rèn)證一樣,不過(guò)很明顯,我們沒(méi)必要每次使用 OpenFeign 調(diào)用別的服務(wù)的時(shí)候,都去傳一堆認(rèn)證信息,我們可以通過(guò)實(shí)現(xiàn)feign.RequestInterceptor
接口來(lái)定義一個(gè) OpenFeign 的請(qǐng)求攔截器,在攔截器中,統(tǒng)一為 OpenFeign 請(qǐng)求設(shè)置請(qǐng)求頭信息。
以上就是“如何實(shí)現(xiàn)微服務(wù)鑒權(quán)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。