在SpringBoot中集成JWT鑒權(quán)的方法

在SpringBoot中集成JWT鑒權(quán)的方法?這個(gè)問(wèn)題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見(jiàn)到的。希望通過(guò)這個(gè)問(wèn)題能讓你收獲頗深。下面是小編給大家?guī)?lái)的參考內(nèi)容,讓我們一起來(lái)看看吧!

創(chuàng)新互聯(lián)是一家業(yè)務(wù)范圍包括IDC托管業(yè)務(wù),雅安服務(wù)器托管、主機(jī)租用、主機(jī)托管,四川、重慶、廣東電信服務(wù)器租用,四川雅安電信機(jī)房,成都網(wǎng)通服務(wù)器托管,成都服務(wù)器租用,業(yè)務(wù)范圍遍及中國(guó)大陸、港澳臺(tái)以及歐美等多個(gè)國(guó)家及地區(qū)的互聯(lián)網(wǎng)數(shù)據(jù)服務(wù)公司。

1、關(guān)于JWT

1.1 什么是JWT

老生常談的開(kāi)頭,我們要用這樣一種工具,首先得知道以下幾個(gè)問(wèn)題。

  • 這個(gè)工具是什么,這個(gè)工具解決了什么問(wèn)題
  • 是否適用于當(dāng)前我們所處得業(yè)務(wù)場(chǎng)景
  • 用了之后是否會(huì)帶來(lái)任何其他問(wèn)題
  • 怎么用才是最佳實(shí)踐

那什么是JWT呢?以下是我對(duì)jwt官網(wǎng)上對(duì)JWT介紹的翻譯。

JSON Web Token (JWT)是一種定義了一種緊湊并且獨(dú)立的,用于在各方之間使用JSON對(duì)象安全的傳輸信息的一個(gè)開(kāi)放標(biāo)準(zhǔn)(RFC 7519)。

現(xiàn)在我們知道,JWT其實(shí)是一種開(kāi)放標(biāo)準(zhǔn),用于在多點(diǎn)之間安全地傳輸用JSON表示的數(shù)據(jù)。在傳輸?shù)倪^(guò)程中,JWT以字符串的形式出現(xiàn)在我們的視野中。該字符串中的信息可以通過(guò)數(shù)字簽名進(jìn)行驗(yàn)證和信任。(推薦:Java教程)

1.2 應(yīng)用場(chǎng)景

JWT在實(shí)際的開(kāi)發(fā)中,有哪些應(yīng)用場(chǎng)景呢?

1.2.1 授權(quán)

這應(yīng)該算是JWT最常見(jiàn)的使用場(chǎng)景。在前端界面中,一旦用戶登錄成功,會(huì)接收到后端返回的JWT。后續(xù)的請(qǐng)求都會(huì)包含后端返回的JWT,作為對(duì)后端路由、服務(wù)以及資源的訪問(wèn)的憑證。

1.2.2 信息交換

利用JWT在多方之間相互傳遞信息具有一定的安全性,例如JWT可以用HMAC、RSA非對(duì)稱加密算法以及ECDSA數(shù)字簽名算法對(duì)JWT進(jìn)行簽名,可以確保消息的發(fā)送者是真的發(fā)送者,而且使用header和payload進(jìn)行的簽名計(jì)算,我們還可以驗(yàn)證發(fā)送的消息是否被篡改了。

2.JWT的結(jié)構(gòu)

通俗來(lái)講JWT由header.payload.signature三部分組成的字符串,網(wǎng)上有太多帖子介紹這一塊了,所以在這里就簡(jiǎn)單介紹一下就好了。

2.1 header

header由使用的簽名算法和令牌的類型的組成,例如令牌的類型就是JWT這種開(kāi)放標(biāo)準(zhǔn),而使用的簽名算法就是HS256,也就是HmacSHA256算法。其他的加密算法還有HmacSHA512、SHA512withECDSA等等。

然后將這個(gè)包含兩個(gè)屬性的JSON對(duì)象轉(zhuǎn)化為字符串然后使用Base64編碼,最終形成了JWT的header。

2.2 payload

payload說(shuō)直白一些就類似你的requestBody中的數(shù)據(jù)。只不過(guò)是分了三種類型,預(yù)先申明好的、自定義的以及私有的。像iss發(fā)件人,exp過(guò)期時(shí)間都是預(yù)先注冊(cè)好的申明。

預(yù)先申明在載荷中的數(shù)據(jù)不是強(qiáng)制性的使用,但是官方建議使用。然后這串類似于requestBody的JSON經(jīng)過(guò)Base64編碼形成了JWT的第二部分。

2.3 signature

如果要生成signature,就需要使用jwt自定義配置項(xiàng)中的secret,也就是Hmac算法加密所需要的密鑰。將之前經(jīng)過(guò)Base64編碼的header和payload用.相連,再使用自定義的密鑰,對(duì)該消息進(jìn)行簽名,最終生成了簽名。

生成的簽名用于驗(yàn)證消息在傳輸?shù)倪^(guò)程中沒(méi)有被更改。在使用非對(duì)稱加密算法進(jìn)行簽名的時(shí)候,還可以用于驗(yàn)證JWT的發(fā)件人是否與payload中申明的發(fā)件人是同一個(gè)人。

3.JWT在Spring項(xiàng)目中的應(yīng)用場(chǎng)景

3.1 生成JWT

代碼如下。

public String createJwt(String userId, String projectId) throws IllegalArgumentException, UnsupportedEncodingException {
    Algorithm al = Algorithm.HMAC256(secret);
    Instant instant = LocalDateTime.now().plusHours(outHours).atZone(ZoneId.systemDefault()).toInstant();
    Date expire = Date.from(instant);
    String token = JWT.create()
            .withIssuer(issuer)
            .withSubject("userInfo")
            .withClaim("user_id", userId)
            .withClaim("project_id", projectId)
            .withExpiresAt(expire)
            .sign(al);
    return token;
}

傳入的兩個(gè)Claim是項(xiàng)目里自定義的payload,al是選擇的算法,而secret就是對(duì)信息簽名的密鑰,subject則是該token的主題,withExpiresAt標(biāo)識(shí)了該token的過(guò)期時(shí)間。

3.2 返回JWT

在用戶登錄系統(tǒng)成功之后,將token作為返回參數(shù),返回給前端。

3.3 驗(yàn)證token

在token返回給前端之后,后端要做的就是驗(yàn)證這個(gè)token是否是合法的,是否可以訪問(wèn)服務(wù)器的資源。主要可以通過(guò)以下幾種方式去驗(yàn)證。

3.3.1 解析token

使用JWTVerifier解析token,這是驗(yàn)證token是否合法的第一步,例如前端傳過(guò)來(lái)的token是一串沒(méi)有任何意義的字符串,在這一步就可以拋出錯(cuò)誤。示例代碼如下。

try {
    Algorithm algorithm = Algorithm.HMAC256(secret);
    JWTVerifier verifier = JWT.require(algorithm).build();
    DecodedJWT jwt = verifier.verify(token);
} catch (JWTVerificationException e) {
    e.printStackTrace();
}

JWTVerifier可以使用用制定secret簽名的算法,指定的claim來(lái)驗(yàn)證token的合法性。

3.3.2 判斷token時(shí)效性

判斷了token是有效的之后,再對(duì)token的時(shí)效性進(jìn)行驗(yàn)證。

try {
    Algorithm algorithm = Algorithm.HMAC256(secret);
    JWTVerifier verifier = JWT.require(algorithm).build();
    DecodedJWT jwt = verifier.verify(token);
    if (jwt.getExpiresAt().before(new Date())) {
        System.out.println("token已過(guò)期");
        return null;
    }
} catch (JWTVerificationException e) {
    e.printStackTrace();
    return null;
}

如果該token過(guò)期了,則不允許訪問(wèn)服務(wù)器資源。具體的流程如下。

在SpringBoot中集成JWT鑒權(quán)的方法

3.3.3 刷新過(guò)期時(shí)間

上面創(chuàng)建token的有效時(shí)間是可以配置的,假設(shè)是2個(gè)小時(shí),并且用戶登錄進(jìn)來(lái)連續(xù)工作了1小時(shí)59分鐘,在進(jìn)行一個(gè)很重要的操作的時(shí)候,點(diǎn)擊確定,這個(gè)時(shí)候token過(guò)期了。如果程序沒(méi)有保護(hù)策略,那么用戶接近兩個(gè)小時(shí)的工作就成為了無(wú)用功。

遇到這樣的問(wèn)題,我們之前的流程設(shè)計(jì)必然面對(duì)一次重構(gòu)。可能大家會(huì)有疑問(wèn),不就是在用戶登錄之后,每次操作對(duì)去刷新一次token的過(guò)期時(shí)間嗎?

那么問(wèn)題來(lái)了,我們知道token是由header.payload.signature三段內(nèi)容組成的,而過(guò)期時(shí)間則是屬于payload,如果改變了過(guò)期的時(shí)間,那么最終生成的payload的hash則勢(shì)必與上一次生成的不同。

換句話說(shuō),這是一個(gè)全新的token。前端要怎么接收這個(gè)全新的token呢?可想到的解決方案無(wú)非就是每次請(qǐng)求,根據(jù)response header中的返回不斷的刷新的token。但是這樣的方式侵入了前端開(kāi)發(fā)的業(yè)務(wù)層。使其每一個(gè)接口都需要去刷新token。

大家可能會(huì)說(shuō),無(wú)非就是加一個(gè)攔截器嘛,對(duì)業(yè)務(wù)侵入不大啊。即使這部分邏輯是寫在攔截器里的,但是前端因?yàn)閠oken鑒權(quán)的邏輯而多出了這部分代碼。而這部分代碼從職能分工上來(lái)說(shuō),其實(shí)是后端的邏輯。

說(shuō)的直白一些,刷新token,對(duì)token的時(shí)效性進(jìn)行管理,應(yīng)該是由后端來(lái)做。前端不需要也不應(yīng)該去關(guān)心這一部分的邏輯。

3.3.4 redis大法好

綜上所述,刷新token的過(guò)期時(shí)間勢(shì)必要放到后端,并且不能通過(guò)判斷JWT中payload中的expire來(lái)判斷token是否有效。

所以,在用戶登錄成功之后并將token返回給前端的同時(shí),需要以某一個(gè)唯一表示為key,當(dāng)前的token為value,寫入Redis緩存中。并且在每次用戶請(qǐng)求成功后,刷新token的過(guò)期時(shí)間,流程如下所示。

在SpringBoot中集成JWT鑒權(quán)的方法

經(jīng)過(guò)這樣的重構(gòu)之后,流程就變成了這樣。

在SpringBoot中集成JWT鑒權(quán)的方法

在流程中多了一個(gè)刷新token的流程。只要用戶登錄了系統(tǒng),每一次的操作都會(huì)刷新token的過(guò)期時(shí)間,就不會(huì)出現(xiàn)之前說(shuō)的在進(jìn)行某個(gè)操作時(shí)突然失效所造成數(shù)據(jù)丟失的情況。

在用戶登錄之后的兩個(gè)小時(shí)內(nèi),如果用戶沒(méi)有進(jìn)行任何操作,那么2小時(shí)后再次請(qǐng)求接口就會(huì)直接被服務(wù)器拒絕訪問(wèn)。

4.總結(jié)

總的來(lái)說(shuō),JWT中是不建議放特別敏感信息的。如果沒(méi)有用非對(duì)稱加密算法的話,把token復(fù)制之后直接可以去jwt官網(wǎng)在線解析。如果請(qǐng)求被攔截到了,里面的所有信息等于是透明的。

但是JWT可以用來(lái)當(dāng)作一段時(shí)間內(nèi)運(yùn)行訪問(wèn)服務(wù)器資源的憑證。例如JWT的payload中帶有userId這個(gè)字段,那么就可以對(duì)該token標(biāo)識(shí)的用戶的合法性進(jìn)行驗(yàn)證。例如,該用戶當(dāng)前狀態(tài)是否被鎖定?該userId所標(biāo)識(shí)的用戶是否存在于我們的系統(tǒng)?等等。

并且通過(guò)實(shí)現(xiàn)token的公用,可以實(shí)現(xiàn)用戶的多端同時(shí)登錄。像之前的登錄之后創(chuàng)建token,就限定了用戶只能同時(shí)在一臺(tái)設(shè)備上登錄。

感謝各位的閱讀!看完上述內(nèi)容,你們對(duì)在SpringBoot中集成JWT鑒權(quán)的方法大概了解了嗎?希望文章內(nèi)容對(duì)大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁(yè)題目:在SpringBoot中集成JWT鑒權(quán)的方法
網(wǎng)頁(yè)地址:http://muchs.cn/article22/ispgjc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開(kāi)發(fā)、全網(wǎng)營(yíng)銷推廣域名注冊(cè)、網(wǎng)站設(shè)計(jì)、自適應(yīng)網(wǎng)站、網(wǎng)站維護(hù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁(yè)設(shè)計(jì)公司