JAVA后端實(shí)現(xiàn)JWT令牌的示例
首先解釋一下JWT,在此之前,我們需要明確為什么需要JWT
登陸校驗(yàn)
其實(shí)最常見的應(yīng)用場景就是登陸校驗(yàn),我們希望某個(gè)用戶在初次打開網(wǎng)址時(shí),首先應(yīng)該進(jìn)行登陸操作,而不是直接訪問某個(gè)功能,并且在登陸之后,訪問其他功能時(shí)不需要再次登陸。在此前提下,應(yīng)運(yùn)而生三種登陸校驗(yàn)方式,下面我們一一講解。
會(huì)話跟蹤
什么是會(huì)話,我們摒棄其他科普詞條繁雜的專業(yè)詞匯介紹,我們就這樣認(rèn)為:你去買東西,從你走進(jìn)了一家商店開始,你就開始了你和“商店”的會(huì)話,你買完東西走出商店,此次會(huì)話結(jié)束。在這里面,“你”就是瀏覽器,“商店”就是服務(wù)器。我們買東西,不可能每買一個(gè),都需要重新進(jìn)入商店(登錄),也不可能不進(jìn)入商店,就可以買東西(舉例,以線下商店為例)。
接下來我們正式講解什么是會(huì)話跟蹤,詞條解釋是這樣的:一種維護(hù)瀏覽器狀態(tài)的方法,服務(wù)器需要識(shí)別多次請(qǐng)求是否來自于同一瀏覽器,以便在同一次會(huì)話的多次請(qǐng)求間共享數(shù)據(jù)。
為什么我們需要會(huì)話跟蹤,這是因?yàn)镠TTP協(xié)議是一種無狀態(tài)的協(xié)議。所謂無狀態(tài),指的是每一次請(qǐng)求都是獨(dú)立的,下一次請(qǐng)求并不會(huì)攜帶上一次請(qǐng)求的數(shù)據(jù)。而瀏覽器與服務(wù)器之間進(jìn)行交互,基于HTTP協(xié)議也就意味著現(xiàn)在我們通過瀏覽器來訪問了登陸這個(gè)接口,實(shí)現(xiàn)了登陸的操作,接下來我們?cè)趫?zhí)行其他業(yè)務(wù)操作時(shí),服務(wù)器也并不知道這個(gè)員工到底登陸了沒有。因?yàn)镠TTP協(xié)議是無狀態(tài)的,兩次請(qǐng)求之間是獨(dú)立的,所以是無法判斷這個(gè)員工到底登陸了沒有。因此我們需要會(huì)話跟蹤,去“記錄”交互操作。
我們有三種會(huì)話跟蹤技術(shù),分別是:cookie、session、令牌(只需了解jwt的可以跳過前兩項(xiàng)介紹)
cookie
cookie 是客戶端會(huì)話跟蹤技術(shù),它是存儲(chǔ)在客戶端瀏覽器的,我們使用 cookie 來跟蹤會(huì)話,我們就可以在瀏覽器第一次發(fā)起請(qǐng)求來請(qǐng)求服務(wù)器的時(shí)候,我們?cè)诜?wù)器端來設(shè)置一個(gè)cookie。
比如第一次請(qǐng)求了登錄接口,登錄接口執(zhí)行完成之后,我們就可以設(shè)置一個(gè)cookie,在 cookie 當(dāng)中我們就可以來存儲(chǔ)用戶相關(guān)的一些數(shù)據(jù)信息。比如我可以在 cookie 當(dāng)中來存儲(chǔ)當(dāng)前登錄用戶的用戶名,用戶的ID。
服務(wù)器端在給客戶端在響應(yīng)數(shù)據(jù)的時(shí)候,會(huì)自動(dòng)的將 cookie 響應(yīng)給瀏覽器,瀏覽器接收到響應(yīng)回來的 cookie 之后,會(huì)自動(dòng)的將 cookie 的值存儲(chǔ)在瀏覽器本地。接下來在后續(xù)的每一次請(qǐng)求當(dāng)中,都會(huì)將瀏覽器本地所存儲(chǔ)的 cookie 自動(dòng)地?cái)y帶到服務(wù)端。
切記,以上三步都是自動(dòng)進(jìn)行。那么為什么會(huì)自動(dòng)進(jìn)行?
因?yàn)?cookie 它是 HTP 協(xié)議當(dāng)中所支持的技術(shù),而各大瀏覽器廠商都支持了這一標(biāo)準(zhǔn)。在 HTTP 協(xié)議官方給我們提供了一個(gè)響應(yīng)頭和請(qǐng)求頭:
響應(yīng)頭 Set-Cookie :設(shè)置Cookie數(shù)據(jù)的
請(qǐng)求頭 Cookie:攜帶Cookie數(shù)據(jù)的
接下來在服務(wù)端我們就可以獲取到 cookie 的值。我們可以去判斷一下這個(gè) cookie 的值是否存在,如果不存在這個(gè)cookie,就說明客戶端之前是沒有訪問登錄接口的;如果存在 cookie 的值,就說明客戶端之前已經(jīng)登錄完成了。這樣我們就可以基于 cookie 在同一次會(huì)話的不同請(qǐng)求之間來共享數(shù)據(jù)。
我們使用代碼實(shí)現(xiàn):
@Slf4j @RestController public class SessionController { //設(shè)置Cookie @GetMapping("/c1") public Result cookie1(HttpServletResponse response){ response.addCookie(new Cookie("login_username","itheima")); //設(shè)置Cookie/響應(yīng)Cookie return Result.success(); } //獲取Cookie @GetMapping("/c2") public Result cookie2(HttpServletRequest request){ Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { if(cookie.getName().equals("login_username")){ System.out.println("login_username: "+cookie.getValue()); //輸出name為login_username的cookie } } return Result.success(); } }
訪問c1接口,設(shè)置Cookie,http://localhost:8080/c1
我們可以看到,設(shè)置的cookie,通過響應(yīng)頭Set-Cookie響應(yīng)給瀏覽器,并且瀏覽器會(huì)將Cookie,存儲(chǔ)在瀏覽器端。
訪問c2接口 http://localhost:8080/c2,此時(shí)瀏覽器會(huì)自動(dòng)的將Cookie攜帶到服務(wù)端。
優(yōu)點(diǎn):HTTP協(xié)議中支持的技術(shù)(像Set-Cookie 響應(yīng)頭的解析以及 Cookie 請(qǐng)求頭數(shù)據(jù)的攜帶,都是瀏覽器自動(dòng)進(jìn)行的,是無需我們手動(dòng)操作的)
缺點(diǎn):
移動(dòng)端APP(Android、IOS)中無法使用Cookie
不安全,用戶可以自己禁用Cookie
Cookie不能跨域(跨域參考:http://www.dbjr.com.cn/javascript/333320pbv.htm)
session
其實(shí)session的底層就是基于我們剛才所介紹的 Cookie 來實(shí)現(xiàn)的。
獲取Session
如果我們現(xiàn)在要基于 Session 來進(jìn)行會(huì)話跟蹤,瀏覽器在第一次請(qǐng)求服務(wù)器的時(shí)候,我們就可以直接在服務(wù)器當(dāng)中來獲取到會(huì)話對(duì)象Session。如果是第一次請(qǐng)求Session ,會(huì)話對(duì)象是不存在的,這個(gè)時(shí)候服務(wù)器會(huì)自動(dòng)的創(chuàng)建一個(gè)會(huì)話對(duì)象Session 。而每一個(gè)會(huì)話對(duì)象Session ,它都有一個(gè)ID(示意圖中Session后面括號(hào)中的1,就表示ID),我們稱之為 Session 的ID。
響應(yīng)Cookie (JSESSIONID)
接下來,服務(wù)器端在給瀏覽器響應(yīng)數(shù)據(jù)的時(shí)候,它會(huì)將 Session 的 ID 通過 Cookie 響應(yīng)給瀏覽器。其實(shí)在響應(yīng)頭當(dāng)中增加了一個(gè) Set-Cookie 響應(yīng)頭。這個(gè) Set-Cookie 響應(yīng)頭對(duì)應(yīng)的值是不是cookie? cookie 的名字是固定的 JSESSIONID 代表的服務(wù)器端會(huì)話對(duì)象 Session 的 ID。瀏覽器會(huì)自動(dòng)識(shí)別這個(gè)響應(yīng)頭,然后自動(dòng)將Cookie存儲(chǔ)在瀏覽器本地。
查找Session
接下來,在后續(xù)的每一次請(qǐng)求當(dāng)中,都會(huì)將 Cookie 的數(shù)據(jù)獲取出來,并且攜帶到服務(wù)端。接下來服務(wù)器拿到JSESSIONID這個(gè) Cookie 的值,也就是 Session 的ID。拿到 ID 之后,就會(huì)從眾多的 Session 當(dāng)中來找到當(dāng)前請(qǐng)求對(duì)應(yīng)的會(huì)話對(duì)象Session。
這樣我們是不是就可以通過 Session 會(huì)話對(duì)象在同一次會(huì)話的多次請(qǐng)求之間來共享數(shù)據(jù)了?好,這就是基于 Session 進(jìn)行會(huì)話跟蹤的流程。
我們使用代碼實(shí)現(xiàn):
@Slf4j @RestController public class SessionController { @GetMapping("/s1") public Result session1(HttpSession session){ log.info("HttpSession-s1: {}", session.hashCode()); session.setAttribute("loginUser", "tom"); //往session中存儲(chǔ)數(shù)據(jù) return Result.success(); } @GetMapping("/s2") public Result session2(HttpServletRequest request){ HttpSession session = request.getSession(); log.info("HttpSession-s2: {}", session.hashCode()); Object loginUser = session.getAttribute("loginUser"); //從session中獲取數(shù)據(jù) log.info("loginUser: {}", loginUser); return Result.success(loginUser); } }
訪問 s1 接口,http://localhost:8080/s1
請(qǐng)求完成之后,在響應(yīng)頭中,就會(huì)看到有一個(gè)Set-Cookie的響應(yīng)頭,里面響應(yīng)回來了一個(gè)Cookie,就是JSESSIONID,這個(gè)就是服務(wù)端會(huì)話對(duì)象 Session 的ID。
訪問 s2 接口,http://localhost:8080/s2
接下來,在后續(xù)的每次請(qǐng)求時(shí),都會(huì)將Cookie的值,攜帶到服務(wù)端,那服務(wù)端呢,接收到Cookie之后,會(huì)自動(dòng)的根據(jù)JSESSIONID的值,找到對(duì)應(yīng)的會(huì)話對(duì)象Session。 兩次請(qǐng)求,獲取到的Session會(huì)話對(duì)象的hashcode是一樣的,就說明是同一個(gè)會(huì)話對(duì)象。而且,第一次請(qǐng)求時(shí),往Session會(huì)話對(duì)象中存儲(chǔ)的值,第二次請(qǐng)求時(shí),也獲取到了。 那這樣,我們就可以通過Session會(huì)話對(duì)象,在同一個(gè)會(huì)話的多次請(qǐng)求之間來進(jìn)行數(shù)據(jù)共享了。
優(yōu)缺點(diǎn)
優(yōu)點(diǎn):Session是存儲(chǔ)在服務(wù)端的,安全
缺點(diǎn):
服務(wù)器集群環(huán)境下無法直接使用Session
移動(dòng)端APP(Android、IOS)中無法使用Cookie
用戶可以自己禁用Cookie
Cookie不能跨域
是的,想必你們也發(fā)現(xiàn)了,cookie的缺點(diǎn),session也有,畢竟session就是基于cookie實(shí)現(xiàn)的。
下面我們開始本文目標(biāo):JWT
令牌
這里我們所提到的令牌,其實(shí)它就是一個(gè)用戶身份的標(biāo)識(shí),看似很高大上,很神秘,其實(shí)本質(zhì)就是一個(gè)字符串。想必很多90后都曾經(jīng)擁有過一個(gè)實(shí)體的QQ令牌,并且現(xiàn)在Steam也有登錄的令牌。實(shí)質(zhì)上他們的功能作用是一樣的。其實(shí)它就是一個(gè)用戶身份的標(biāo)識(shí),本質(zhì)就是一個(gè)字符串。
如果通過令牌技術(shù)來跟蹤會(huì)話,我們就可以在瀏覽器發(fā)起請(qǐng)求。在請(qǐng)求登錄接口的時(shí)候,如果登錄成功,我就可以生成一個(gè)令牌,令牌就是用戶的合法身份憑證。接下來我在響應(yīng)數(shù)據(jù)的時(shí)候,我就可以直接將令牌響應(yīng)給前端。
接下來我們?cè)谇岸顺绦虍?dāng)中接收到令牌之后,就需要將這個(gè)令牌存儲(chǔ)起來。這個(gè)存儲(chǔ)可以存儲(chǔ)在 cookie 當(dāng)中,也可以存儲(chǔ)在其他的存儲(chǔ)空間(比如:localStorage)當(dāng)中。
接下來,在后續(xù)的每一次請(qǐng)求當(dāng)中,都需要將令牌攜帶到服務(wù)端。攜帶到服務(wù)端之后,接下來我們就需要來校驗(yàn)令牌的有效性。如果令牌是有效的,就說明用戶已經(jīng)執(zhí)行了登錄操作,如果令牌是無效的,就說明用戶之前并未執(zhí)行登錄操作。
此時(shí),如果是在同一次會(huì)話的多次請(qǐng)求之間,我們想共享數(shù)據(jù),我們就可以將共享的數(shù)據(jù)存儲(chǔ)在令牌當(dāng)中就可以了。
優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
支持PC端、移動(dòng)端
解決集群環(huán)境下的認(rèn)證問題
減輕服務(wù)器的存儲(chǔ)壓力(無需在服務(wù)器端存儲(chǔ))
缺點(diǎn):需要自己實(shí)現(xiàn)(包括令牌的生成、令牌的傳遞、令牌的校驗(yàn))
針對(duì)于這三種方案,現(xiàn)在企業(yè)開發(fā)當(dāng)中使用的最多的就是第三種令牌技術(shù)進(jìn)行會(huì)話跟蹤。而前面的這兩種傳統(tǒng)的方案,現(xiàn)在企業(yè)項(xiàng)目開發(fā)當(dāng)中已經(jīng)很少使用了。所以在我們的課程當(dāng)中,我們也將會(huì)采用令牌技術(shù)來解決案例項(xiàng)目當(dāng)中的會(huì)話跟蹤問題。
JWT
JWT全稱:JSON Web Token (官網(wǎng):JSON Web Tokens - jwt.io)
定義了一種簡潔的、自包含的格式,用于在通信雙方以json數(shù)據(jù)格式安全的傳輸信息。由于數(shù)字簽名的存在,這些信息是可靠的。
簡潔:是指jwt就是一個(gè)簡單的字符串??梢栽谡?qǐng)求參數(shù)或者是請(qǐng)求頭當(dāng)中直接傳遞。
自包含:指的是jwt令牌,看似是一個(gè)隨機(jī)的字符串,但是我們是可以根據(jù)自身的需求在jwt令牌中存儲(chǔ)自定義的數(shù)據(jù)內(nèi)容。如:可以直接在jwt令牌中存儲(chǔ)用戶的相關(guān)信息。
簡單來講,jwt就是將原始的json數(shù)據(jù)格式進(jìn)行了安全的封裝,這樣就可以直接基于jwt在通信雙方安全的進(jìn)行信息傳輸了。
JWT的組成: (JWT令牌由三個(gè)部分組成,三個(gè)部分之間使用英文的點(diǎn)來分割)
第一部分:Header(頭), 記錄令牌類型、簽名算法等。 例如:{"alg":"HS256","type":"JWT"}
第二部分:Payload(有效載荷),攜帶一些自定義信息、默認(rèn)信息等。 例如:{"id":"1","username":"Tom"}
第三部分:Signature(簽名),防止Token被篡改、確保安全性。將header、payload,并加入指定秘鑰,通過指定簽名算法計(jì)算而來。
簽名的目的就是為了防jwt令牌被篡改,而正是因?yàn)閖wt令牌最后一個(gè)部分?jǐn)?shù)字簽名的存在,所以整個(gè)jwt 令牌是非常安全可靠的。一旦jwt令牌當(dāng)中任何一個(gè)部分、任何一個(gè)字符被篡改了,整個(gè)令牌在校驗(yàn)的時(shí)候都會(huì)失敗,所以它是非常安全可靠的。
JWT是如何將原始的JSON格式數(shù)據(jù),轉(zhuǎn)變?yōu)樽址哪兀?/p>
其實(shí)在生成JWT令牌時(shí),會(huì)對(duì)JSON格式的數(shù)據(jù)進(jìn)行一次編碼:進(jìn)行base64編碼
Base64:是一種基于64個(gè)可打印的字符來表示二進(jìn)制數(shù)據(jù)的編碼方式。既然能編碼,那也就意味著也能解碼。所使用的64個(gè)字符分別是A到Z、a到z、 0- 9,一個(gè)加號(hào),一個(gè)斜杠,加起來就是64個(gè)字符。任何數(shù)據(jù)經(jīng)過base64編碼之后,最終就會(huì)通過這64個(gè)字符來表示。當(dāng)然還有一個(gè)符號(hào),那就是等號(hào)。等號(hào)它是一個(gè)補(bǔ)位的符號(hào)
需要注意的是Base64是編碼方式,而不是加密方式。
JWT令牌最典型的應(yīng)用場景就是登錄認(rèn)證:
1. 在瀏覽器發(fā)起請(qǐng)求來執(zhí)行登錄操作,此時(shí)會(huì)訪問登錄的接口,如果登錄成功之后,我們需要生成一個(gè)jwt令牌,將生成的 jwt令牌返回給前端。
2. 前端拿到j(luò)wt令牌之后,會(huì)將jwt令牌存儲(chǔ)起來。在后續(xù)的每一次請(qǐng)求中都會(huì)將jwt令牌攜帶到服務(wù)端。
3. 服務(wù)端統(tǒng)一攔截請(qǐng)求之后,先來判斷一下這次請(qǐng)求有沒有把令牌帶過來,如果沒有帶過來,直接拒絕訪問,如果帶過來了,還要校驗(yàn)一下令牌是否是有效。如果有效,就直接放行進(jìn)行請(qǐng)求的處理。
在JWT登錄認(rèn)證的場景中我們發(fā)現(xiàn),整個(gè)流程當(dāng)中涉及到兩步操作:
1. 在登錄成功之后,要生成令牌。
2. 每一次請(qǐng)求當(dāng)中,要接收令牌并對(duì)令牌進(jìn)行校驗(yàn)。
簡單介紹了JWT令牌以及JWT令牌的組成之后,接下來我們就來學(xué)習(xí)基于Java代碼如何生成和校驗(yàn)JWT令牌。
首先我們先來實(shí)現(xiàn)JWT令牌的生成。要想使用JWT令牌,需要先引入JWT的依賴:
<!-- JWT依賴--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
接下來我們生成算法:
@Test public void genJwt(){ Map<String,Object> claims = new HashMap<>(); claims.put("id",1); claims.put("username","HongKongDoll"); String jwt = Jwts.builder() .setClaims(claims) //自定義內(nèi)容(載荷) .signWith(SignatureAlgorithm.HS256, "bug,start") //簽名算法 .setExpiration(new Date(System.currentTimeMillis() + 24*3600*1000)) //有效期 .compact(); System.out.println(jwt); }
走你:
這時(shí)我們使用utools上的插件進(jìn)行解碼(或者找任一在線解碼網(wǎng)站都可)
第一部分解析出來,看到JSON格式的原始數(shù)據(jù),所使用的簽名算法為HS256。
第二個(gè)部分是我們自定義的數(shù)據(jù),之前我們自定義的數(shù)據(jù)就是id,還有一個(gè)exp代表的是我們所設(shè)置的過期時(shí)間。
由于前兩個(gè)部分是base64編碼,所以是可以直接解碼出來。但最后一個(gè)部分并不是base64編碼,是經(jīng)過簽名算法計(jì)算出來的,所以最后一個(gè)部分是不會(huì)解析的。
實(shí)現(xiàn)了JWT令牌的生成,下面我們接著使用Java代碼來校驗(yàn)JWT令牌(解析生成的令牌):
@Test public void parseJwt(){ Claims claims = Jwts.parser() .setSigningKey("bug,start")//指定簽名密鑰(必須保證和生成令牌時(shí)使用相同的簽名密鑰) .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNzA0ODU1NTk5LCJ1c2VybmFtZSI6IkhvbmdLb25nRG9sbCJ9.JLg62R07Zr_IEZtaZ4oAQNkGoNIdGKrLbcy-OUCTTPU") .getBody(); System.out.println(claims); }
走我:
令牌解析后,我們可以看到id和過期時(shí)間,如果在解析的過程當(dāng)中沒有報(bào)錯(cuò),就說明解析成功了。
接下來,為了驗(yàn)證JWT的可靠性,我們修改JWT中其中任一字母,重新進(jìn)行解析:
走他:
我只是把第一位的e換成了E,結(jié)果就報(bào)錯(cuò):JWT解析異常。說明解析JWT只要修改其中任一字符,就會(huì)解析失敗。
這時(shí)候又有一位未來首付要問了,那么還有其他的解析失敗因素嗎?當(dāng)然有啦,那就是過期時(shí)間,我們?cè)谏厦嬖O(shè)置了過期時(shí)間,那么我們現(xiàn)在把生成策略中過期時(shí)間換成1秒過期:
我們重新解析一下:
這次報(bào)的是JWT過期異常。
通過以上測(cè)試,我們?cè)谑褂肑WT令牌時(shí)需要注意:
JWT校驗(yàn)時(shí)使用的簽名秘鑰,必須和生成JWT令牌時(shí)使用的秘鑰是配套的。
如果JWT令牌解析校驗(yàn)時(shí)報(bào)錯(cuò),則說明 JWT令牌被篡改 或 過期失效了,令牌非法。
接下來,我們進(jìn)入實(shí)戰(zhàn)部分:
JWT令牌的生成和校驗(yàn)的基本操作我們已經(jīng)學(xué)習(xí)完了,接下來我們就需要在案例當(dāng)中通過JWT令牌技術(shù)來跟蹤會(huì)話。具體的思路我們前面已經(jīng)分析過了,主要就是兩步操作:
生成令牌
在登錄成功之后來生成一個(gè)JWT令牌,并且把這個(gè)令牌直接返回給前端校驗(yàn)令牌
攔截前端請(qǐng)求,從請(qǐng)求中獲取到令牌,對(duì)令牌進(jìn)行解析校驗(yàn)
那我們首先來完成:登錄成功之后生成JWT令牌,并且把令牌返回給前端。
在controller同級(jí)下,建一個(gè)包,用來放我們的工具類,然后新建一個(gè)class:
/** * @Description JWT工具類 * @Author QingNing * @Date 2024/1/9 */ package com.ycg.vue.utils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; import java.util.Map; public class JwtUtils { private static final String signKey = "bug,start";//簽名密鑰 private static final Long expire = 3600000L; //有效時(shí)間 /** * 生成JWT令牌 * @param claims JWT第二部分負(fù)載 payload 中存儲(chǔ)的內(nèi)容 * @return */ public static String generateJwt(Map<String, Object> claims){ String jwt = Jwts.builder() .addClaims(claims)//自定義信息(有效載荷) .signWith(SignatureAlgorithm.HS256, signKey)//簽名算法(頭部) .setExpiration(new Date(System.currentTimeMillis() + expire))//過期時(shí)間 .compact(); return jwt; } /** * 解析JWT令牌 * @param jwt JWT令牌 * @return JWT第二部分負(fù)載 payload 中存儲(chǔ)的內(nèi)容 */ public static Claims parseJWT(String jwt){ Claims claims = Jwts.parser() .setSigningKey(signKey)//指定簽名密鑰 .parseClaimsJws(jwt)//指定令牌Token .getBody(); return claims; } }
然后在登陸功能中添加JWT生成策略:
以下是本人的登陸代碼,僅做參考
@ApiOperation(value = "用戶登錄") @PostMapping("/login") public result user(@RequestBody UserVo userVo){ User user = userService.login(userVo); //非空判斷 if(!Objects.isNull(user)){ //生成 Map<String , Object> claims = new HashMap<>(); claims.put("id", user.getId()); claims.put("username",user.getUsername()); //使用JWT工具類,生成身份令牌 String token = JwtUtils.generateJwt(claims); return result.success(token); } return result.error("用戶名或密碼錯(cuò)誤,請(qǐng)重新輸入"); }
我們打開swagger進(jìn)行查看是否成功。
我們發(fā)現(xiàn),已經(jīng)返回了token,后續(xù)的每一次請(qǐng)求當(dāng)中,都會(huì)將這個(gè)令牌攜帶到服務(wù)端。
此時(shí)我們只需要在前端的返回方法中,添加回調(diào)方法:
即可將jwt令牌存到請(qǐng)求頭中,在進(jìn)行其他操作時(shí)就會(huì)攜帶jwt令牌,直至本次會(huì)話結(jié)束。后續(xù)可以使用攔截器進(jìn)行判斷。
至此,我們就完成了JWT令牌的實(shí)現(xiàn)。
到此這篇關(guān)于JAVA后端實(shí)現(xiàn)JWT令牌的示例的文章就介紹到這了,更多相關(guān)JAVA JWT令牌內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章

AndroidQ沙盒機(jī)制之分區(qū)存儲(chǔ)適配

一文詳解SpringBoot?Redis多數(shù)據(jù)源配置

Java 位運(yùn)算符>>與>>>區(qū)別案例詳解

使用自定義注解實(shí)現(xiàn)redisson分布式鎖