SpringBoot集成Auth0 JWT的示例代碼
前言
說說JWT,先說下互聯(lián)網服務常見的兩種用戶認證方式:
session認證與Token認證
session認證
傳統(tǒng)的Session認證的大體流程可以表示為用戶提供用戶名和密碼登錄后由服務器存儲一份用戶登錄信息并傳遞給瀏覽器保存為Cookie,并在下次請求中根據(jù)Cookie來識別用戶,但這種方式缺陷明顯:
- Session都是保存在內存中,隨著認證用戶的增多,服務端的開銷明顯增大
- 保存在內存中的Session限制了分布式的應用
- Cookie容易被截獲偽造
Token認證
Token 泛指身份驗證時使用的令牌,Token鑒權機制從某些角度而言與Cookie是一個作用,其目的是讓后臺知道請求是來自于受信的客戶端,其通過實現(xiàn)了某種算法加密的Token字符串來完成鑒權工作,其優(yōu)點在于:
- 服務器不需要保存 Session 數(shù)據(jù)(無狀態(tài)),容易實現(xiàn)擴展
- 有效避免Cookie被截獲引發(fā)的CSRF攻擊
- 可以存儲一些業(yè)務邏輯所必要的非敏感信息
- 便于傳輸,其構成非常簡單,字節(jié)占用小
JWT簡介
JWT定義
JWT全稱為Json web token,也就是 Json 格式的 web token,可以這么理解:
Token // 個人證件
JWT // 個人身份證
JWT數(shù)據(jù)結構
JWT由三段字符串組成,中間用.分隔,如下:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInNjb3BlIjo4LCJleHAiOjE3MTU3NDAyMjIsImlhdCI6MTYyOTM0MDIyMn0.wuRsF5wvLHbDF_21Pocas8SeXQ315rgBl6wm1LRL2bQ
JWT 的三個部分依次如下:
- Header(頭部)// Header 部分是一個 JSON 對象,描述 JWT 的元數(shù)據(jù),通常是下面的樣子。
- Payload(負載)// Payload 部分是一個 JSON 對象,用來存放實際需要傳遞的數(shù)據(jù)
- Signature(簽名)// Signature 部分是對前兩部分的簽名,防止數(shù)據(jù)篡改
第一段字符串Header:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
將其 Base64 解碼后得到:
{ "typ": "JWT", // TOKEN TYPE ,token類型 "alg": "HS256" //ALGORITHM,算法 哈希256 }
第二段字符串Payload:eyJ1aWQiOjEsInNjb3BlIjo4LCJleHAiOjE3MTU3NDAyMjIsImlhdCI6MTYyOTM0MDIyMn0
PAYLOAD是數(shù)據(jù)載體,可以有自定義數(shù)據(jù)
{ "uid": "1234567890" // 自定義數(shù)據(jù) }
第三段字符串Signature:wuRsF5wvLHbDF_21Pocas8SeXQ315rgBl6wm1LRL2bQ
Signature 部分是對前兩部分的簽名,防止數(shù)據(jù)篡改。
JWT的類庫
Java 中的 JWT 有很多類庫,關于其優(yōu)缺點可以在官網查看:https://jwt.io/,這里我們介紹Auth0的JWT的集成使用方式
Auth0 實現(xiàn)的 com.auth0 / java-jwt / 3.3.0
Brian Campbell 實現(xiàn)的 org.bitbucket.b_c / jose4j / 0.6.3
connect2id 實現(xiàn)的 com.nimbusds / nimbus-jose-jwt / 5.7
Les Hazlewood 實現(xiàn)的 io.jsonwebtoken / jjwt / 0.9.0
FusionAuth 實現(xiàn)的 io.fusionauth / fusionauth-jwt / 3.1.0
Vert.x 實現(xiàn)的 io.vertx / vertx-auth-jwt / 3.5.1
具體實現(xiàn)
JWT配置
pom.xml
<!-- jwt --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.1</version> </dependency>
application.yml
coisini: security: jwt-key: coisini # 過期時間 token-expired-in: 86400000
JWT工具類
JwtUtil.java
import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTVerificationException; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.*; /** * @Description JWT工具類 * @author coisini * @date Aug 18, 2021 * @Version 1.0 */ @Component public class JwtUtil { /** * key */ private static String jwtKey; /** * 過期時間 */ private static Integer expiredTimeIn; /** * JWT KEY * @param jwtKey */ @Value("${coisini.security.jwt-key}") public void setJwtKey(String jwtKey) { JwtUtil.jwtKey = jwtKey; } /** * 過期時間 * @param expiredTimeIn */ @Value("${coisini.security.token-expired-in}") public void setExpiredTimeIn(Integer expiredTimeIn) { JwtUtil.expiredTimeIn = expiredTimeIn; } /** * 生成令牌 * @param uid 用戶id * @return */ public static String makeToken(Long uid) { return JwtUtil.getToken(uid); } /** * 獲取令牌 * @param uid 用戶id * @param scope 權限分級數(shù)字 * @return */ private static String getToken(Long uid) { // 指定算法 Algorithm algorithm = Algorithm.HMAC256(JwtUtil.jwtKey); Map<String, Date> dateMap = JwtUtil.calculateExpiredIssues(); /** * withClaim() 寫入自定義數(shù)據(jù) * withExpiresAt() 設置過期時間 * withIssuedAt() 設置當前時間 * sign() 簽名算法 */ return JWT.create() .withClaim("uid", uid) .withExpiresAt(dateMap.get("expiredTime")) .withIssuedAt(dateMap.get("now")) .sign(algorithm); } /** * 獲取自定義數(shù)據(jù) * @param token * @return */ public static Optional<Map<String, Claim>> getClaims(String token) { DecodedJWT decodedJWT; // 指定算法 Algorithm algorithm = Algorithm.HMAC256(JwtUtil.jwtKey); JWTVerifier jwtVerifier = JWT.require(algorithm).build(); try { decodedJWT = jwtVerifier.verify(token); } catch (JWTVerificationException e) { return Optional.empty(); } return Optional.of(decodedJWT.getClaims()); } /** * 驗證Token * @param token * @return */ public static boolean verifyToken(String token) { try { Algorithm algorithm = Algorithm.HMAC256(JwtUtil.jwtKey); JWTVerifier jwtVerifier = JWT.require(algorithm).build(); jwtVerifier.verify(token); } catch (JWTVerificationException e) { return false; } return true; } /** * 計算過期時間 * @return */ private static Map<String, Date> calculateExpiredIssues() { Map<String, Date> map = new HashMap<>(); Calendar calendar = Calendar.getInstance(); Date now = calendar.getTime(); calendar.add(Calendar.SECOND, JwtUtil.expiredTimeIn); // 當前時間 map.put("now", now); // 過期時間 map.put("expiredTime", calendar.getTime()); return map; } }
測試接口
JwtController.java
@RestController @RequestMapping("/jwt") public class JwtController { /** * 獲取Token * @param id * @return */ @GetMapping(value = "/get") public String getToken(@RequestParam Long id) { return JwtUtil.makeToken(id); } /** * 驗證Token * @param token * @return */ @PostMapping("/verify") public Map<String, Boolean> verify(@RequestParam String token) { Map<String, Boolean> map = new HashMap<>(); Boolean valid = JwtUtil.verifyToken(token); map.put("is_valid", valid); return map; } }
測試結果
JWT生成的Token應該放在請求頭內來傳輸,后端統(tǒng)一攔截驗證,這里留在下篇文章吧。。。
到此這篇關于SpringBoot集成Auth0 JWT的示例代碼的文章就介紹到這了,更多相關SpringBoot集成Auth0 JWT內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- SpringBoot+Spring Security+JWT實現(xiàn)RESTful Api權限控制的方法
- SpringBoot整合SpringSecurity和JWT的示例
- SpringBoot集成JWT實現(xiàn)token驗證的流程
- spring boot如何基于JWT實現(xiàn)單點登錄詳解
- 基于springboot+jwt實現(xiàn)刷新token過程解析
- SpringBoot集成JWT生成token及校驗方法過程解析
- SpringBoot使用JWT實現(xiàn)登錄驗證的方法示例
- Spring-boot結合Shrio實現(xiàn)JWT的方法
- 在SpringBoot中使用JWT的實現(xiàn)方法
相關文章
java實現(xiàn)在性能測試中進行業(yè)務驗證實例
這篇文章主要為大家介紹了java實現(xiàn)在性能測試中進行業(yè)務驗證實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07mybatis簡介與配置_動力節(jié)點Java學院整理
這篇文章主要介紹了mybatis簡介與配置,介紹了MyBatis+Spring+MySql簡單配置,有興趣的可以了解一下2017-09-09如何基于Springboot完成新增員工功能并設置全局異常處理器
最近工作中遇到了做一個管理員工信息的功能,下面這篇文章主要給大家介紹了關于如何基于Springboot完成新增員工功能并設置全局異常處理器的相關資料,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2022-11-11java數(shù)字圖像處理基礎使用imageio寫圖像文件示例
這篇文章主要介紹了Java 2D的圖像處理API,文章討論和提及的API都是基于JDK6的,Java中寫一個圖像文件使用ImageIO對象即可,下面看代碼吧2014-01-01