SpringBoot集成Auth0 JWT的示例代碼
前言
說說JWT,先說下互聯(lián)網(wǎng)服務(wù)常見的兩種用戶認(rèn)證方式:
session認(rèn)證與Token認(rèn)證
session認(rèn)證
傳統(tǒng)的Session認(rèn)證的大體流程可以表示為用戶提供用戶名和密碼登錄后由服務(wù)器存儲(chǔ)一份用戶登錄信息并傳遞給瀏覽器保存為Cookie,并在下次請(qǐng)求中根據(jù)Cookie來識(shí)別用戶,但這種方式缺陷明顯:
- Session都是保存在內(nèi)存中,隨著認(rèn)證用戶的增多,服務(wù)端的開銷明顯增大
- 保存在內(nèi)存中的Session限制了分布式的應(yīng)用
- Cookie容易被截獲偽造
Token認(rèn)證
Token 泛指身份驗(yàn)證時(shí)使用的令牌,Token鑒權(quán)機(jī)制從某些角度而言與Cookie是一個(gè)作用,其目的是讓后臺(tái)知道請(qǐng)求是來自于受信的客戶端,其通過實(shí)現(xiàn)了某種算法加密的Token字符串來完成鑒權(quán)工作,其優(yōu)點(diǎn)在于:
- 服務(wù)器不需要保存 Session 數(shù)據(jù)(無狀態(tài)),容易實(shí)現(xiàn)擴(kuò)展
- 有效避免Cookie被截獲引發(fā)的CSRF攻擊
- 可以存儲(chǔ)一些業(yè)務(wù)邏輯所必要的非敏感信息
- 便于傳輸,其構(gòu)成非常簡單,字節(jié)占用小
JWT簡介
JWT定義
JWT全稱為Json web token,也就是 Json 格式的 web token,可以這么理解:
Token // 個(gè)人證件
JWT // 個(gè)人身份證
JWT數(shù)據(jù)結(jié)構(gòu)
JWT由三段字符串組成,中間用.分隔,如下:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInNjb3BlIjo4LCJleHAiOjE3MTU3NDAyMjIsImlhdCI6MTYyOTM0MDIyMn0.wuRsF5wvLHbDF_21Pocas8SeXQ315rgBl6wm1LRL2bQ
JWT 的三個(gè)部分依次如下:
- Header(頭部)// Header 部分是一個(gè) JSON 對(duì)象,描述 JWT 的元數(shù)據(jù),通常是下面的樣子。
- Payload(負(fù)載)// Payload 部分是一個(gè) JSON 對(duì)象,用來存放實(shí)際需要傳遞的數(shù)據(jù)
- Signature(簽名)// Signature 部分是對(duì)前兩部分的簽名,防止數(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 部分是對(duì)前兩部分的簽名,防止數(shù)據(jù)篡改。
JWT的類庫
Java 中的 JWT 有很多類庫,關(guān)于其優(yōu)缺點(diǎn)可以在官網(wǎng)查看:https://jwt.io/,這里我們介紹Auth0的JWT的集成使用方式
Auth0 實(shí)現(xiàn)的 com.auth0 / java-jwt / 3.3.0
Brian Campbell 實(shí)現(xiàn)的 org.bitbucket.b_c / jose4j / 0.6.3
connect2id 實(shí)現(xiàn)的 com.nimbusds / nimbus-jose-jwt / 5.7
Les Hazlewood 實(shí)現(xiàn)的 io.jsonwebtoken / jjwt / 0.9.0
FusionAuth 實(shí)現(xiàn)的 io.fusionauth / fusionauth-jwt / 3.1.0
Vert.x 實(shí)現(xiàn)的 io.vertx / vertx-auth-jwt / 3.5.1
具體實(shí)現(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
# 過期時(shí)間
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;
/**
* 過期時(shí)間
*/
private static Integer expiredTimeIn;
/**
* JWT KEY
* @param jwtKey
*/
@Value("${coisini.security.jwt-key}")
public void setJwtKey(String jwtKey) {
JwtUtil.jwtKey = jwtKey;
}
/**
* 過期時(shí)間
* @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 權(quán)限分級(jí)數(shù)字
* @return
*/
private static String getToken(Long uid) {
// 指定算法
Algorithm algorithm = Algorithm.HMAC256(JwtUtil.jwtKey);
Map<String, Date> dateMap = JwtUtil.calculateExpiredIssues();
/**
* withClaim() 寫入自定義數(shù)據(jù)
* withExpiresAt() 設(shè)置過期時(shí)間
* withIssuedAt() 設(shè)置當(dāng)前時(shí)間
* 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());
}
/**
* 驗(yàn)證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;
}
/**
* 計(jì)算過期時(shí)間
* @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);
// 當(dāng)前時(shí)間
map.put("now", now);
// 過期時(shí)間
map.put("expiredTime", calendar.getTime());
return map;
}
}
測(cè)試接口
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);
}
/**
* 驗(yàn)證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;
}
}
測(cè)試結(jié)果


JWT生成的Token應(yīng)該放在請(qǐng)求頭內(nèi)來傳輸,后端統(tǒng)一攔截驗(yàn)證,這里留在下篇文章吧。。。
到此這篇關(guān)于SpringBoot集成Auth0 JWT的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot集成Auth0 JWT內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot+Spring Security+JWT實(shí)現(xiàn)RESTful Api權(quán)限控制的方法
- SpringBoot整合SpringSecurity和JWT的示例
- SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證的流程
- spring boot如何基于JWT實(shí)現(xiàn)單點(diǎn)登錄詳解
- 基于springboot+jwt實(shí)現(xiàn)刷新token過程解析
- SpringBoot集成JWT生成token及校驗(yàn)方法過程解析
- SpringBoot使用JWT實(shí)現(xiàn)登錄驗(yàn)證的方法示例
- Spring-boot結(jié)合Shrio實(shí)現(xiàn)JWT的方法
- 在SpringBoot中使用JWT的實(shí)現(xiàn)方法
相關(guān)文章
elasticsearch索引index之put?mapping的設(shè)置分析
這篇文章主要為大家介紹了elasticsearch索引index之put?mapping的設(shè)置分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
關(guān)于JavaEE匿名內(nèi)部類和Lambda表達(dá)式的注意事項(xiàng)
這篇文章主要介紹了關(guān)于JavaEE匿名內(nèi)部類和Lambda表達(dá)式的注意事項(xiàng),匿名內(nèi)部類顧名思義是沒有修飾符甚至沒有名稱的內(nèi)部類,使用匿名內(nèi)部類需要注意哪些地方,我們一起來看看吧2023-03-03
SpringBoot favicon Chrome設(shè)置問題解決方案
在本篇文章里小編給大家分享的是關(guān)于SpringBoot favicon Chrome設(shè)置問題實(shí)例內(nèi)容,小的朋友們可以參考學(xué)習(xí)下。2020-02-02
SpringCloud?Gateway之請(qǐng)求應(yīng)答日志打印方式
這篇文章主要介紹了SpringCloud?Gateway之請(qǐng)求應(yīng)答日志打印方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
java 中@Deprecated 注解的實(shí)例詳解
這篇文章主要介紹了java 中@Deprecated 注解的實(shí)例詳解的相關(guān)資料,這里對(duì)@Deprecated注解進(jìn)行了詳細(xì)介紹,希望能幫助到大家,需要的朋友可以參考下2017-08-08
SpringBoot?實(shí)現(xiàn)流控的操作方法
本文介紹了限流算法的基本概念和常見的限流算法,包括計(jì)數(shù)器算法、漏桶算法和令牌桶算法,還介紹了如何在Spring?Boot中使用Guava庫和自定義注解以及AOP實(shí)現(xiàn)接口限流功能,感興趣的朋友一起看看吧2024-12-12
Spring如何基于aop實(shí)現(xiàn)事務(wù)控制
這篇文章主要介紹了Spring如何基于aop實(shí)現(xiàn)事務(wù)控制,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
JavaWeb response和request對(duì)象原理及實(shí)例解析
這篇文章主要介紹了JavaWeb response和request對(duì)象原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11

