JWT实现-jjwt 作者:马育民 • 2026-04-01 17:15 • 阅读:10001 # 介绍 **JJWT**(**J**ava **J**WT)是 **Java 生态里最主流、企业用得最多的 JWT 工具库**,专门用来在后端(SpringBoot/SpringCloud 等)**生成、签名、解析、验证 JWT 令牌**,做登录鉴权、接口授权、微服务间身份传递。 --- ## 一、JJWT 是什么 - 全称:**Java JWT**(Java JSON Web Token) - 定位:**纯 Java 实现的 JWT 开源库**,完全遵循 **RFC 7519(JWT)、RFC 7515(JWS)、RFC 7516(JWE)** 等规范 - 适用:**SpringBoot 2/3、微服务、单体应用、Android** 等 JVM 环境 - 特点:**API 简洁、链式调用、安全校验强、异常清晰** --- ## 二、核心能力(你代码里用到的就是这些) ### 1. 生成 JWT(签发) - 存放用户信息:**claims(自定义数据)**、**subject(用户名)** - 标准字段:签发时间 **issuedAt**、过期时间 **expiration** - 签名防篡改:**signWith(密钥)**(HMAC/RSA/ECDSA) - 最终生成:**compact()** → 一段 `xxx.yyy.zzz` 字符串 ### 2. 解析与验证(你代码里的 parser) - 验签:**verifyWith(密钥)** → 确保没被篡改 - 自动校验:**过期、签名错误、格式非法** 直接抛异常 - 取数据:**parseSignedClaims(token).getPayload()** → 拿到用户信息 ### 3. 支持的算法(企业常用) - **对称签名(简单安全)**:HS256 / HS384 / HS512(你现在用的就是这类) - **非对称(更高安全)**:RS256 / ES256 / PS256(适合微服务/公钥分发) --- ## 三、版本与依赖 ### 1. 主流版本(企业最稳) - **0.9.x**:老版,API 不同(已淘汰) - **0.11.x**:过渡版 - **0.12.x**:**当前企业主流、最推荐** ### 2. 0.12.x 关键变化(和你代码直接相关) - **新 API**: - 签名:`signWith(SecretKey)`(不再传算法) - 解析:`verifyWith(SecretKey).build().parseSignedClaims()` - **强制安全**: - HMAC 密钥 **必须 ≥32 字节**(你代码里 `secret` 要够长) - 自动拒绝弱算法、弱密钥 ## 版本选择 ### 一、企业存量项目(最多、最稳):**0.11.5** - **现状**:**80% 以上老项目、Spring Boot 2.x 主流在用** - 特点: - 稳定、无坑、文档/案例最多 - 兼容 **JDK 8 ~ 17**、Spring Boot 2.x - 依赖拆分:`jjwt-api` + `jjwt-impl` + `jjwt-jackson` - API:`parserBuilder()`、`signWith(key, alg)` 风格 - 为什么流行: - 0.11.x 是 **长期稳定分支**,修复了大量安全漏洞(含 CVE 防护) - 很多公司技术栈锁在 **Spring Boot 2.7.x / JDK 11**,配套就是 **0.11.5** ### 二、新项目 / Spring Boot 3 标配:**0.12.3 ~ 0.12.5** - **你现在用的 0.12.5 就是这个阵营的最新稳定版** - 特点: - **原生支持 Spring Boot 3 / Jakarta EE(jakarta.servlet)** - 简化依赖:**单 jar `jjwt` 包含全部(api+impl+jackson)** - API 更简洁:`Jwts.builder().signWith(key)`、`parser().verifyWith(key).build()` - 更强安全校验(拒绝伪签名、不合规 JWT) - 适用: - **Spring Boot 3.0+、JDK 17+ 新项目必选** - 你现在的版本 **完全正确、企业主流、可直接上生产** ### 三、过时版本(不要再用) - **0.9.1 及更早**: - 非常老、API 不兼容、**不支持 Spring Boot 3** - 方法:`setSigningKey(String)`、`parser().setSigningKey()` 已废弃 # springboot3 实现 JWT ### 提醒 **SpringBoot3 必须用 JJWT 0.12.3+ 版本!** 旧版 JJWT(0.9.1)不支持 SpringBoot3(Jakarta),会直接报错! ### 一、pom.xml 依赖(直接复制) ```xml io.jsonwebtoken jjwt-api 0.12.3 io.jsonwebtoken jjwt-impl 0.12.3 runtime io.jsonwebtoken jjwt-jackson 0.12.3 runtime ``` --- ### 二、application.yml 配置 ```yaml # JWT 配置 jwt: secret: yourSecretKeyyourSecretKeyyourSecretKeyyourSecretKey # 密钥要足够长 expire: 86400000 # 过期时间 1天 ``` --- ### 三、JWT 工具类 `JwtUtil.java` ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.crypto.SecretKey; import java.util.Date; import java.util.Map; /** * JWT工具类 * 用于生成Token、解析Token、校验Token、从Token中获取用户信息 * 适配 jjwt 0.12.3+ 版本 & SpringBoot3 */ @Component public class JwtUtil { /** * JWT 密钥 * 从配置文件读取,长度必须 >=32 位,用于签名加密 */ @Value("${jwt.secret}") private String secret; /** * Token 过期时间 * 从配置文件读取,单位:毫秒 */ @Value("${jwt.expire}") private Long expire; /** * 获取加密密钥 * 将配置的字符串密钥转为 JJWT 需要的 SecretKey 对象 */ private SecretKey getSecretKey() { return Keys.hmacShaKeyFor(secret.getBytes()); } /** * 生成 JWT Token * @param claims 自定义载荷(存放用户ID、角色等信息) * @param username 用户名(作为Token的唯一标识) * @return 生成好的 Token 字符串 */ public String generateToken(Map claims, String username) { return Jwts.builder() .claims(claims) // 设置自定义载荷(存放额外信息) .subject(username) // 设置主题(一般放用户名/账号) .issuedAt(new Date()) // 设置签发时间(当前时间) .expiration(new Date(System.currentTimeMillis() + expire)) // 设置过期时间 .signWith(getSecretKey())// 使用密钥签名(保证Token不被篡改) .compact(); // 生成最终的 Token 字符串 } /** * 解析 Token,获取载荷(Claims) * 会自动校验:签名是否正确 + 是否过期 * @param token 前端传入的 Token * @return Token 中的载荷数据 */ public Claims extractClaims(String token) { return Jwts.parser() .verifyWith(getSecretKey()) // 设置密钥,用于校验签名 .build() // 构建解析器 .parseSignedClaims(token) // 解析并校验 Token .getPayload(); // 获取 Token 中的有效载荷 } /** * 从 Token 中提取用户名 */ public String extractUsername(String token) { return extractClaims(token).getSubject(); } /** * 判断 Token 是否过期 * true = 已过期 * false = 未过期 */ public boolean isExpired(String token) { return extractClaims(token).getExpiration().before(new Date()); } } ``` --- ### 四、登录接口(返回 Token) ```java @PostMapping("/api/users/login") public Result login(@RequestBody User user) { // 1. 校验用户名密码(你自己写) User loginUser = userService.getUserByUsername(user.getUsername()); if (loginUser == null || !loginUser.getPassword().equals(user.getPassword())) { // 你现在收到的错误就是这里! return Result.fail(401, "用户名或密码错误"); } // 2. 生成 JWT token Map claims = new HashMap<>(); claims.put("userId", loginUser.getId()); String token = jwtUtil.generateToken(claims, user.getUsername()); // 3. 返回 token return Result.success(token); } ``` --- ### 五、前端 axios 携带 Token(你需要的) ```js axios.post('http://localhost:8080/api/users/login', { username: 'admin', password: '123456' }).then(res => { const token = res.data; localStorage.setItem('token', token); }) // 以后请求携带 token axios.get('http://localhost:8080/api/user/info', { headers: { 'Authorization': 'Bearer ' + localStorage.getItem('token') } }) ``` 原文出处:http://malaoshi.top/show_1GW33K55hN7X.html