SpringBoot-JWT生成Token和攔截器的使用(訪問(wèn)受限資源)
1.什么是JWT
JWT官方的定義是:JSON Web令牌(JWT)是一個(gè)開(kāi)放標(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è)人中心頁(yè)面信息、購(gòu)物車頁(yè)面信息)
比如說(shuō)現(xiàn)在在你家樓下有一家有一家自助餐廳,自助餐廳的門(mén)前有一個(gè)收銀柜臺(tái)。到了中午你感覺(jué)到肚子餓了,去了自助餐廳吃飯,去收銀柜臺(tái)交了錢,收銀柜臺(tái)給你開(kāi)了一張你交過(guò)錢的證明,該證明里寫(xiě)了你什么時(shí)候交的錢,交了多少錢等信息,現(xiàn)在你拿著這張證明去餐廳里面吃飯,吃飯時(shí)候只要給這張證明就行,因?yàn)樗J(rèn)證了你的信息,店員知道你交過(guò)錢了也不會(huì)讓你再交一次,同時(shí)防止了你不交錢吃飯的情況。
在這個(gè)例子中,我們?nèi)绻褕?chǎng)景轉(zhuǎn)換到網(wǎng)上商城(前后端分離的情況),收銀柜臺(tái)就是登錄,登錄完后服務(wù)器給你一個(gè)證明,證明你登錄過(guò)了,這個(gè)證明有生成的時(shí)間、你的信息等等,這時(shí)候你想訪問(wèn)購(gòu)物車,就拿著這個(gè)證明發(fā)給服務(wù)器,服務(wù)器驗(yàn)證該證明,驗(yàn)證通過(guò)后返回給你想要的數(shù)據(jù)。
還有一種情況就是如果你沒(méi)有登錄,想直接訪問(wèn)購(gòu)物車的數(shù)據(jù),服務(wù)器會(huì)發(fā)現(xiàn)你沒(méi)有token(或者你偽造了一個(gè)token服務(wù)器驗(yàn)證不通過(guò)或者token過(guò)期),就會(huì)讓你重新登錄,從而實(shí)現(xiàn)了攔截訪問(wè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è)置過(guò)期時(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)證不通過(guò)就會(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, "登錄過(guò)期,請(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開(kāi)頭的請(qǐng)求,因?yàn)閡ser開(kāi)頭請(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和攔截器的使用(訪問(wèn)受限資源)的文章就介紹到這了,更多相關(guān)SpringBoot-JWT生成Token和攔截器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springcloud seata nacos環(huán)境搭建過(guò)程圖解
這篇文章主要介紹了Springcloud seata nacos環(huán)境搭建過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
解決spring AOP中自身方法調(diào)用無(wú)法應(yīng)用代理的問(wèn)題
這篇文章主要介紹了解決spring AOP中自身方法調(diào)用無(wú)法應(yīng)用代理的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
springboot加載命令行參數(shù)ApplicationArguments的實(shí)現(xiàn)
本文主要介紹了springboot加載命令行參數(shù)ApplicationArguments的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
InterProcessMutex實(shí)現(xiàn)zookeeper分布式鎖原理
本文主要介紹了InterProcessMutex實(shí)現(xiàn)zookeeper分布式鎖原理,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Java內(nèi)存模型相關(guān)知識(shí)總結(jié)
這篇文章主要介紹了Java內(nèi)存模型相關(guān)知識(shí)總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
Java讀取制表符文本轉(zhuǎn)換為JSON實(shí)現(xiàn)實(shí)例
在Java開(kāi)發(fā)中,處理各種數(shù)據(jù)格式是常見(jiàn)的任務(wù),本文將介紹如何使用Java讀取制表符文本文件,并將其轉(zhuǎn)換為JSON格式,以便于后續(xù)的數(shù)據(jù)處理和分析,我們將使用Java中的相關(guān)庫(kù)來(lái)實(shí)現(xiàn)這個(gè)過(guò)程,并提供詳細(xì)的代碼示例2024-01-01
Java后臺(tái)通過(guò)Collections獲取list集合中最大數(shù),最小數(shù)代碼
這篇文章主要介紹了Java后臺(tái)通過(guò)Collections獲取list集合中最大數(shù),最小數(shù)代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08

