SpringBootSecurity學(xué)習(xí)(13)前后端分離版之JWT

JWT 使用

前面簡(jiǎn)單介紹了把默認(rèn)的頁面登錄改為前后端分離的接口異步登錄的方法怖亭,可以幫我們實(shí)現(xiàn)基本的前后端分離登錄功能涎显。但是這種基本的登錄和前面的頁面登錄還有一個(gè)一樣的地方,就是使用session和cookie來維護(hù)登錄狀態(tài)兴猩,這種方法的問題在于期吓,擴(kuò)展性不好。單機(jī)當(dāng)然沒有問題倾芝,如果是服務(wù)器集群讨勤,或者是跨域的服務(wù)導(dǎo)向架構(gòu),就要求 session 數(shù)據(jù)共享晨另,每臺(tái)服務(wù)器都能夠讀取 session潭千。

一種解決方案是 session 數(shù)據(jù)持久化,寫入redis或別的持久層借尿。各種服務(wù)收到請(qǐng)求后刨晴,都向持久層請(qǐng)求數(shù)據(jù)屉来。這種方案的優(yōu)點(diǎn)是架構(gòu)清晰,缺點(diǎn)是工程量比較大狈癞。另外茄靠,持久層萬一掛了,就會(huì)單點(diǎn)失敗蝶桶。

另一種方案是服務(wù)器索性不保存 session 數(shù)據(jù)了嘹黔,所有數(shù)據(jù)都保存在客戶端,每次請(qǐng)求都發(fā)回服務(wù)器莫瞬。JWT 就是這種方案的一個(gè)代表儡蔓。關(guān)于JWT的理論知識(shí),建議參考 阮一峰 大神寫的教程 :JSON Web Token 入門教程疼邀,這是我認(rèn)為可能是寫的最清晰的一個(gè)喂江,下面的jwt的實(shí)現(xiàn)也是根據(jù)此教程來實(shí)現(xiàn)。

具體的理論知識(shí)可以參考教程旁振,這里簡(jiǎn)單說下流程获询,用戶登錄成功后,在header中返回用戶一個(gè)token信息拐袜,這個(gè)信息里面包含了加密的用戶信息和數(shù)字簽名吉嚣,最重要的還有過期時(shí)間,客戶端接到后蹬铺,每次訪問接口header中都帶著這個(gè)token尝哆,服務(wù)端驗(yàn)證成功后就表示處于登錄狀態(tài),過期后再從新獲取即可甜攀。

具體的token內(nèi)容包含了頭部(加密信息)秋泄,載體(用戶信息),簽名(簽名兩個(gè)部分的前面)三大塊规阀,三大塊之間用英文句號(hào)(也就是 ".")連接起來恒序,組成一個(gè)完整的token信息

流程設(shè)計(jì)

根據(jù)前面的理論知識(shí),我們來設(shè)計(jì)一下如何使用jwt谁撼。首先我們使用jwt歧胁,就可以不再使用session和cookie,所以第一步就是:

  1. 在security配置文件中配置session為無狀態(tài)厉碟。

然后考慮構(gòu)建jwt消息體喊巍,有三個(gè)部分,第一個(gè)部分就是頭部墨榄,內(nèi)容是加密類型:

file

上面代碼中玄糟,alg屬性表示簽名的算法(algorithm),默認(rèn)是 HMAC SHA256(寫成 HS256)袄秩;typ屬性表示這個(gè)令牌(token)的類型(type)阵翎,JWT 令牌統(tǒng)一寫為JWT逢并,最后,將上面的 JSON 對(duì)象使用 Base64URL 算法轉(zhuǎn)成字符串郭卫,作為第一部分砍聊。所以第二步就是:

  1. 在security配置文件中配置session為無狀態(tài)。
  2. 確定header信息格式

下一步確定第二部分贰军,消息載體(Payload)玻蝌,這也是一個(gè)json對(duì)象,用來存放實(shí)際需要傳遞的數(shù)據(jù)词疼。JWT 規(guī)定了7個(gè)官方字段俯树,供選用:

file

當(dāng)然除了這些還可以加一些其它內(nèi)容,比如用戶信息贰盗,這個(gè) JSON 對(duì)象也要使用 Base64URL 算法轉(zhuǎn)成字符串许饿,所以第三步和第四步就是:

  1. 在security配置文件中配置session為無狀態(tài)。
  2. 確定header信息格式
  3. 確定消息體
  4. 使用 HMAC SHA256 算法 對(duì)header和消息體進(jìn)行簽名作為第三部分

現(xiàn)在token的消息基本組合完成了舵盈,用戶登錄成功和客戶端訪問接口陋率,都要把token放在header里面,名字是 Authorization 秽晚。所以最后一步就是瓦糟,客戶端正常訪問非登錄等接口時(shí),驗(yàn)證token的合法性赴蝇,所以菩浙,總體設(shè)計(jì)流程如下:

  1. 在security配置文件中配置session為無狀態(tài)。
  2. 確定header信息格式
  3. 確定消息體
  4. 使用 HMAC SHA256 算法 對(duì)header和消息體進(jìn)行簽名作為第三部分
  5. 添加過濾器扯再,驗(yàn)證token合法性

修改配置類

上面的流程設(shè)計(jì)完了芍耘,下面我們按照流程修改項(xiàng)目,首先修改security配置類:

file

配置完后熄阻,啟動(dòng)項(xiàng)目,訪問登錄倔约,登錄成功后可以看到秃殉,沒有任何cookie保存下來。

定義JWT工具類

首先來定義幾個(gè)常量:

file

然后定義Base64URL 算法編碼和解碼方法:

file

然后定義HmacSHA256 加密算法和獲取簽名的方法:

file

最后來設(shè)計(jì)一個(gè)簡(jiǎn)單驗(yàn)證token的方法:

file

這樣jwt工具類就設(shè)計(jì)好了浸剩,目前這幾個(gè)方法足夠操作token內(nèi)容钾军。

定義JWT消息對(duì)象

下面來定義jwt的內(nèi)容,其實(shí)內(nèi)容很簡(jiǎn)單绢要,就三個(gè)部分吏恭,因此,定義三個(gè)字段即可:

file

來看一下構(gòu)造方法重罪,

file

這個(gè)構(gòu)造方法很便捷樱哼,使用它創(chuàng)建對(duì)象以后哀九,jwt的三個(gè)部分基本都完成了,header部分和payload部分都編碼了搅幅,簽名也完成了阅束,因此下面重寫toString方法直接可以生成token:

file

從這里可以看出,token整體默認(rèn)是不加密茄唐,但也是可以加密的息裸。生成原始 Token 以后,可以用密鑰再加密一次沪编。因此不要把密碼等重要信息放入token呼盆。

修改登錄成功處理器

用戶登錄成功后,不再把session發(fā)給用戶蚁廓,而是把jwt發(fā)送給用戶宿亡,因此修改登錄成功處理器如下:

file

注意上面手動(dòng)把用戶的密碼信息設(shè)置為null。這里為了方便纳令,直接使用fastjson組合對(duì)象挽荠。

修改實(shí)體類

帶著token訪問接口的時(shí)候,需要把token轉(zhuǎn)回登錄用戶對(duì)象平绩,因此我們的用戶實(shí)體類和token中帶的字段名字一致圈匆,來修改一下,先看角色實(shí)體類:

file

再看用戶實(shí)體類:

file

可以看到捏雌,基本的原則就是修改的名字和父類的必要字段名字一致就行跃赚,這也是建議的字段名字。

編寫token驗(yàn)證過濾器

我們把security的session改為無狀態(tài)后性湿,雖然不再傳遞session纬傲,但是security的過濾器并沒有失效,因此造成的效果就是登錄成功后肤频,訪問接口顯示未登錄≈才郏現(xiàn)在我們使用token就要在登錄前加一個(gè)驗(yàn)證token的過濾器饲漾,驗(yàn)證通過后直接把信息放到SecurityContextHolder中。這樣每次登錄靠驗(yàn)證token來判斷是否登錄,不再靠session或链。來看這個(gè)過濾器:

file

這個(gè)過濾器很簡(jiǎn)單隙畜,繼承了 GenericFilterBean 類蒜埋,直接獲取token玖详,判斷token不為空,驗(yàn)證token暑刃,并從token的payload中取出用戶信息厢漩,放入SecurityContextHolder中,驗(yàn)證失敗或者token過期直接返回token錯(cuò)誤岩臣。邏輯很簡(jiǎn)單溜嗜。

最后在security類中宵膨,把這個(gè)過濾器配置到前面:

file

這樣我們自定義的jwt流程就完成了×皇ぃ可以在postman中測(cè)試一下柄驻,首先是登錄:

file

登錄成功后,可以看到header中放著token的信息焙压,然后使用token放入另一個(gè)接口的header中訪問接口鸿脓,可以看到訪問成功:

file

有興趣的可以debug跟蹤一下流程。

JWT的幾個(gè)特點(diǎn)

  • (1)JWT 默認(rèn)是不加密涯曲,但也是可以加密的野哭。生成原始 Token 以后,可以用密鑰再加密一次幻件。

  • (2)JWT 不加密的情況下拨黔,不能將秘密數(shù)據(jù)寫入 JWT。

  • (3)JWT 不僅可以用于認(rèn)證绰沥,也可以用于交換信息篱蝇。有效使用 JWT,可以降低服務(wù)器查詢數(shù)據(jù)庫的次數(shù)徽曲。

  • (4)JWT 的最大缺點(diǎn)是零截,由于服務(wù)器不保存 session 狀態(tài),因此無法在使用過程中廢止某個(gè) token秃臣,或者更改 token 的權(quán)限涧衙。也就是說,一旦 JWT 簽發(fā)了奥此,在到期之前就會(huì)始終有效弧哎,除非服務(wù)器部署額外的邏輯。

  • (5)JWT 本身包含了認(rèn)證信息稚虎,一旦泄露撤嫩,任何人都可以獲得該令牌的所有權(quán)限。為了減少盜用祥绞,JWT 的有效期應(yīng)該設(shè)置得比較短非洲。對(duì)于一些比較重要的權(quán)限,使用時(shí)應(yīng)該再次對(duì)用戶進(jìn)行認(rèn)證蜕径。

  • (6)為了減少盜用,JWT 不應(yīng)該使用 HTTP 協(xié)議明碼傳輸败京,要使用 HTTPS 協(xié)議傳輸兜喻。

代碼地址:https://gitee.com/blueses/spring-boot-security 14

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赡麦,隨后出現(xiàn)的幾起案子朴皆,更是在濱河造成了極大的恐慌帕识,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遂铡,死亡現(xiàn)場(chǎng)離奇詭異肮疗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)扒接,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門伪货,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人钾怔,你說我怎么就攤上這事碱呼。” “怎么了宗侦?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵愚臀,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我矾利,道長(zhǎng)姑裂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任男旗,我火速辦了婚禮舶斧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘剑肯。我一直安慰自己捧毛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布让网。 她就那樣靜靜地躺著呀忧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪溃睹。 梳的紋絲不亂的頭發(fā)上而账,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音因篇,去河邊找鬼泞辐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛竞滓,可吹牛的內(nèi)容都是我干的咐吼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼商佑,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼锯茄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤肌幽,失蹤者是張志新(化名)和其女友劉穎晚碾,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喂急,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡格嘁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了廊移。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糕簿。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖画机,靈堂內(nèi)的尸體忽然破棺而出冶伞,到底是詐尸還是另有隱情,我是刑警寧澤步氏,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布响禽,位于F島的核電站,受9級(jí)特大地震影響荚醒,放射性物質(zhì)發(fā)生泄漏芋类。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一界阁、第九天 我趴在偏房一處隱蔽的房頂上張望侯繁。 院中可真熱鬧,春花似錦泡躯、人聲如沸贮竟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咕别。三九已至,卻和暖如春写穴,著一層夾襖步出監(jiān)牢的瞬間惰拱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工啊送, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留偿短,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓馋没,卻偏偏與公主長(zhǎng)得像昔逗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子篷朵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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