SpringBoot-JWT生成Token和攔截器的使用(訪問受限資源)
1.什么是JWT
JWT官方的定義是:JSON Web令牌(JWT)是一個(gè)開放標(biāo)準(zhǔn)(RFC 7519),用于作為JSON對(duì)象在各方之間安全地傳輸信息。 可以驗(yàn)證和信任該信息,因?yàn)樗菙?shù)字簽名的。 jwt可以使用一個(gè)秘密(使用HMAC算法)或使用RSA或ECDSA的公鑰/私鑰對(duì)進(jìn)行簽名。
其實(shí)他本質(zhì)上就是一個(gè)簽名
,用于驗(yàn)證用戶是否可以請(qǐng)求受限資源
(例如在商城中向服務(wù)器請(qǐng)求個(gè)人中心頁面信息、購(gòu)物車頁面信息)
比如說現(xiàn)在在你家樓下有一家有一家自助餐廳,自助餐廳的門前有一個(gè)收銀柜臺(tái)。到了中午你感覺到肚子餓了,去了自助餐廳吃飯,去收銀柜臺(tái)交了錢,收銀柜臺(tái)給你開了一張你交過錢的證明,該證明里寫了你什么時(shí)候交的錢,交了多少錢等信息,現(xiàn)在你拿著這張證明去餐廳里面吃飯,吃飯時(shí)候只要給這張證明就行,因?yàn)樗J(rèn)證了你的信息,店員知道你交過錢了也不會(huì)讓你再交一次,同時(shí)防止了你不交錢吃飯的情況。
在這個(gè)例子中,我們?nèi)绻褕?chǎng)景轉(zhuǎn)換到網(wǎng)上商城(前后端分離的情況),收銀柜臺(tái)就是登錄,登錄完后服務(wù)器給你一個(gè)證明,證明你登錄過了,這個(gè)證明有生成的時(shí)間、你的信息等等,這時(shí)候你想訪問購(gòu)物車,就拿著這個(gè)證明發(fā)給服務(wù)器,服務(wù)器驗(yàn)證該證明,驗(yàn)證通過后返回給你想要的數(shù)據(jù)。
還有一種情況就是如果你沒有登錄,想直接訪問購(gòu)物車的數(shù)據(jù),服務(wù)器會(huì)發(fā)現(xiàn)你沒有token(或者你偽造了一個(gè)token服務(wù)器驗(yàn)證不通過或者token過期),就會(huì)讓你重新登錄,從而實(shí)現(xiàn)了攔截訪問受限資源的功能。
2.JWT生成token
2.1 添加依賴
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
2.2 生成token
該案例為 在 登錄的Controller中,用戶的賬號(hào)密碼輸入正確,生成token,其中最重要的是token的密碼,驗(yàn)證token時(shí)候需要使用
JwtBuilder builder = Jwts.builder(); String token = builder.setSubject("userName") .setIssuedAt(new Date()) //設(shè)置token生成時(shí)間 .setId(u.getUserId() + "")//設(shè)置tokenID .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000))//設(shè)置過期時(shí)間,現(xiàn)在為設(shè)置 一天 .signWith(SignatureAlgorithm.HS256, "123456")//設(shè)置token密碼,解析token需要使用 .compact();
到此token生成完畢,接著返回給前端,前端收到后將其存在cookie當(dāng)中 這里提供一個(gè)設(shè)置cookie的工具類代碼,設(shè)置或者取出cookie可以直接使用 每次前端發(fā)送請(qǐng)求時(shí)候都在 請(qǐng)求頭
中攜帶token即可
var operator = "="; //取出cookie function getCookieValue(keyStr){ var value = null; var s = window.document.cookie; var arr = s.split("; "); for(var i=0; i<arr.length; i++){ var str = arr[i]; var k = str.split(operator)[0]; var v = str.split(operator)[1]; if(k == keyStr){ value = v; break; } } return value; } //設(shè)置cookie function setCookieValue(key,value){ document.cookie = key+operator+value; }
2.3 使用攔截器解析token
配置攔截器
其中ResultVO和ResStatus為封裝的返回對(duì)象,代碼如下:
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class ResultVO { @ApiModelProperty("響應(yīng)狀態(tài)碼") private Integer code; @ApiModelProperty("響應(yīng)信息") private String msg; @ApiModelProperty("響應(yīng)數(shù)據(jù)") private Object Data; }
public class ResStatus { public static Integer OK = 10000; public static Integer NO = 10001; public static Integer PASS = 20002; }
@Component public class CheckTokenInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //因?yàn)槭窃谡?qǐng)求頭中發(fā)送token,所以第一次請(qǐng)求的方法為"OPTIONS",具體可以看TCP/IP協(xié)議 String method = request.getMethod(); if("OPTIONS".equalsIgnoreCase(method)){ return true; } String token = request.getHeader("token"); System.out.println("token:"+token); if(token == null){ ResultVO resultVO = new ResultVO(ResStatus.NO,"請(qǐng)先登錄",null); doResponse(response,resultVO); }else{ try{ //在jwt中,只要token不合法或者驗(yàn)證不通過就會(huì)拋出異常 JwtParser parser = Jwts.parser(); parser.setSigningKey("123456"); Jws<Claims> claimsJws = parser.parseClaimsJws(token); return true; }catch (ExpiredJwtException e1) { ResultVO resultVO = new ResultVO(ResStatus.PASS, "登錄過期,請(qǐng)重新登錄", null); doResponse(response,resultVO); }catch (UnsupportedJwtException e2){ ResultVO resultVO = new ResultVO(ResStatus.NO, "Token不合法,已記錄惡意IP", null); doResponse(response,resultVO); }catch (Exception e3){ ResultVO resultVO = new ResultVO(ResStatus.NO, "請(qǐng)先登錄", null); doResponse(response,resultVO); } } return false; } @SneakyThrows private void doResponse(HttpServletResponse response, ResultVO resultVO) { response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); String s = new ObjectMapper().writeValueAsString(resultVO); out.print(s); out.flush(); out.close(); } }
設(shè)置攔截器攔截的內(nèi)容
攔截了shopcart的請(qǐng)求,排除了user開頭的請(qǐng)求,因?yàn)閡ser開頭請(qǐng)求負(fù)責(zé)登錄和注冊(cè)不應(yīng)被攔截
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Resource private CheckTokenInterceptor checkTokenInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(checkTokenInterceptor) .addPathPatterns("/shopcart/**") .excludePathPatterns("/user/**"); } }
到此這篇關(guān)于SpringBoot-JWT生成Token和攔截器的使用(訪問受限資源)的文章就介紹到這了,更多相關(guān)SpringBoot-JWT生成Token和攔截器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springcloud seata nacos環(huán)境搭建過程圖解
這篇文章主要介紹了Springcloud seata nacos環(huán)境搭建過程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03解決spring AOP中自身方法調(diào)用無法應(yīng)用代理的問題
這篇文章主要介紹了解決spring AOP中自身方法調(diào)用無法應(yīng)用代理的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08springboot加載命令行參數(shù)ApplicationArguments的實(shí)現(xiàn)
本文主要介紹了springboot加載命令行參數(shù)ApplicationArguments的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04InterProcessMutex實(shí)現(xiàn)zookeeper分布式鎖原理
本文主要介紹了InterProcessMutex實(shí)現(xiàn)zookeeper分布式鎖原理,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03Java內(nèi)存模型相關(guān)知識(shí)總結(jié)
這篇文章主要介紹了Java內(nèi)存模型相關(guān)知識(shí)總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Java讀取制表符文本轉(zhuǎn)換為JSON實(shí)現(xiàn)實(shí)例
在Java開發(fā)中,處理各種數(shù)據(jù)格式是常見的任務(wù),本文將介紹如何使用Java讀取制表符文本文件,并將其轉(zhuǎn)換為JSON格式,以便于后續(xù)的數(shù)據(jù)處理和分析,我們將使用Java中的相關(guān)庫(kù)來實(shí)現(xiàn)這個(gè)過程,并提供詳細(xì)的代碼示例2024-01-01Java后臺(tái)通過Collections獲取list集合中最大數(shù),最小數(shù)代碼
這篇文章主要介紹了Java后臺(tái)通過Collections獲取list集合中最大數(shù),最小數(shù)代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08