Spring Boot 如何集成JWT實現(xiàn)Token驗證
近年來,隨著前后端分離、微服務(wù)等架構(gòu)的興起,傳統(tǒng)的cookie+session身份驗證模式已經(jīng)逐漸被基于Token的身份驗證模式取代。接下來介紹如何在Spring Boot項目中集成JWT實現(xiàn)Token驗證。
一、JWT入門
1.什么是JWT
JWT (Json web token)是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標準((RFC 7519)。它定義了一種緊湊的,自包含的方式,用于通信雙方之間以JSON對象的形式安全傳遞信息。JWT使用HMAC算法或者是RSA的公私秘鑰的數(shù)字簽名技術(shù),所以這些信息是可被驗證和信任的。
JWT官網(wǎng):https://jwt.io/
JWT(Java版)的github地址:https://github.com/jwtk/jjwt
2.JWT的結(jié)構(gòu)
在使用 JWT 前,需要先了解它的組成結(jié)構(gòu)。它是由以下三段信息構(gòu)成的:
Header 頭部(包含簽名和/或加密算法的類型)
Payload 載荷 (存放有效信息)
Signature 簽名/簽證
將這三段信息文本用‘.’連接一起就構(gòu)成完整的JWT字符串,也是就我們需要的Token。如下所示:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0aW1lU3RhbXAiOjE2MzkwNDc1NTMxNjksInVzZXJSb2xlIjoiUk9MRV9BRE1JTiIsInVzZXJJZCI6ImFkbWluIn0.UFQLvaiQ1AThx9Fa4SRqNg-b9HPJ9y1TlgQB4-F3pi0JWT的數(shù)據(jù)結(jié)構(gòu)還是比較復(fù)雜的,Header,Payload,Signature中包含了很多信息,建議大家最好是能夠了解。
3.JWT的請求流程
JWT的請求流程也特別簡單,首先使用賬號登錄獲取Token,然后后面的各種請求,都帶上這個Token即可。具體流程如下:
1. 客戶端發(fā)起登錄請求,傳入賬號密碼;
2. 服務(wù)端使用私鑰創(chuàng)建一個Token;
3. 服務(wù)器返回Token給客戶端;
4. 客戶端向服務(wù)端發(fā)送請求,在請求頭中該Token;
5. 服務(wù)器驗證該Token;
6. 返回結(jié)果。

二、Spring Boot 如何集成JWT
JWT提供了基于Java組件:java-jwt幫助我們在Spring Boot項目中快速集成JWT,接下來進行SpringBoot和JWT的集成。
1.引入JWT依賴
創(chuàng)建普通的Spring Boot項目,修改項目中的pom.xml文件,引入JWT等依賴。示例代碼如下:
<dependency><groupId>com.auth0groupId><artifactId>java-jwtartifactId><version>3.10.3version>dependency><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-webartifactId>dependency>
2.創(chuàng)建&驗證Token
創(chuàng)建通用的處理類TokenUtil,負責創(chuàng)建和驗證Token。示例代碼如下:
public class TokenUtil {("${token.secretKey}")private String secretKey;/*** 加密token.*/public String getToken(String userId, String userRole) {//這個是放到負載payLoad 里面,魔法值可以使用常量類進行封裝.String token = JWT.create().withClaim("userId" ,userId).withClaim("userRole", userRole).withClaim("timeStamp", System.currentTimeMillis()).sign(Algorithm.HMAC256(secretKey));return token;}/*** 解析token.* {* "userId": "weizhong",* "userRole": "ROLE_ADMIN",* "timeStamp": "134143214"* }*/public Map<String, String> parseToken(String token) {HashMap<String, String> map = new HashMap<String, String>();DecodedJWT decodedjwt = JWT.require(Algorithm.HMAC256(secretKey)).build().verify(token);Claim userId = decodedjwt.getClaim("userId");Claim userRole = decodedjwt.getClaim("userRole");Claim timeStamp = decodedjwt.getClaim("timeStamp");map.put("userId", userId.asString());map.put("userRole", userRole.asString());map.put("timeStamp", timeStamp.asLong().toString());return map;}}
3.創(chuàng)建攔截器,驗證Token
創(chuàng)建一個攔截器AuthHandlerInterceptor,負責攔截所有Http請求,驗證Token是否有效。示例代碼如下:
public class AuthHandlerInterceptor implements HandlerInterceptor {TokenUtil tokenUtil;private Long refreshTime;private Long expiresTime;/*** 權(quán)限認證的攔截操作.*/public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {log.info("=======進入攔截器========");// 如果不是映射到方法直接通過,可以訪問資源.if (!(object instanceof HandlerMethod)) {return true;}//為空就返回錯誤String token = httpServletRequest.getHeader("token");if (null == token || "".equals(token.trim())) {return false;}log.info("==============token:" + token);Mapmap = tokenUtil.parseToken(token); String userId = map.get("userId");String userRole = map.get("userRole");long timeOfUse = System.currentTimeMillis() - Long.parseLong(map.get("timeStamp"));//1.判斷 token 是否過期if (timeOfUse < refreshTime) {log.info("token驗證成功");return true;}//超過token刷新時間,刷新 tokenelse if (timeOfUse >= refreshTime && timeOfUse < expiresTime) {httpServletResponse.setHeader("token",tokenUtil.getToken(userId,userRole));log.info("token刷新成功");return true;}//token過期就返回 token 無效.else {throw new TokenAuthExpiredException();}}}
攔截器創(chuàng)建之后,需要將攔截器注冊到Spring Boot中。這和其他的攔截器注冊是一樣的。示例代碼如下:
public class AuthWebMvcConfigurer implements WebMvcConfigurer {AuthHandlerInterceptor authHandlerInterceptor;/*** 給除了 /login 的接口都配置攔截器,攔截轉(zhuǎn)向到 authHandlerInterceptor*/public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(authHandlerInterceptor).addPathPatterns("/**").excludePathPatterns("/login");}}
4.創(chuàng)建控制器
創(chuàng)建TokenTestController控制器,處理HTTP請求。示例代碼如下:
public class TokenTestController {TokenUtil tokenUtil;("/login")public String login( LoginUser user){// 先驗證用戶的賬號密碼,賬號密碼驗證通過之后,生成TokenString role = "ROLE_ADMIN";String token = tokenUtil.getToken(user.username,role);return token;}("/testToken")public String testToken(HttpServletRequest request){String token = request.getHeader("token");tokenUtil.parseToken(token);return "請求成功";}}
5.測試驗證
集成JWT成功之后,接下來驗證Token是否成功,啟動項目。在Postman中調(diào)用相關(guān)接口,驗證功能是否正常。
首先,調(diào)用http://localhost:8080/testToken,獲取token

然后,調(diào)用http://localhost:8080/testToken 驗證token是否有效。

最后
以上,我們就把Spring Boot集成JWT實現(xiàn)Token驗證介紹完了。身份驗證是Web開發(fā)中非?;A(chǔ)的功能,后面還會介紹授權(quán)及權(quán)限管理等內(nèi)容。
