Jwts用于创建和验证 JSON Web Token(JWT) 的开源库详解
在 Java 开发中,提到 Jwts
通常指的是 JJWT(Java JWT)库中的核心工具类 io.jsonwebtoken.Jwts
。JJWT 是一个专门用于创建和验证 JSON Web Token(JWT) 的开源库,而 Jwts
类是其提供的入口工具类,主要用于构建(签名)JWT 和解析(验证并提取内容)JWT。
Jwts 的核心作用
Jwts
类的核心功能围绕 JWT 的生命周期展开,主要包括两大操作:
- 构建并签名 JWT(生成 Token):将业务数据(声明)打包为 JWT,并通过密钥或私钥进行签名,确保 Token 不可篡改。
- 解析并验证 JWT(解析 Token):验证 JWT 的签名有效性,并提取其中的声明(如用户信息、过期时间等)。
一、构建并签名 JWT(生成 Token)
通过 Jwts.builder()
方法创建一个 JWT 构建器(JwtBuilder
),逐步设置 Token 的声明(Claims)和签名参数,最终生成签名的 JWT 字符串。
关键步骤与方法
设置基础声明(必选):
JWT 规范定义了一些标准声明(Claims),Jwts
提供了便捷方法设置这些声明:setIssuer(String iss)
:设置签发者(Issuer)。setSubject(String sub)
:设置主题(Subject,通常是用户标识)。setAudience(String aud)
:设置接收者(Audience)。setExpiration(Date exp)
:设置过期时间(必选,Token 失效时间)。setNotBefore(Date nbf)
:设置生效时间(可选,Token 在此时间前无效)。setIssuedAt(Date iat)
:设置签发时间(默认当前时间,可选)。
设置自定义声明(可选):
通过claim(String name, Object value)
方法添加业务相关的自定义声明(如用户角色、权限等)。设置签名算法和密钥:
通过signWith(SignatureAlgorithm alg, Key key)
方法指定签名算法(如 HMAC SHA256、RSA 等)和对应的密钥(对称或非对称)。
示例:生成 JWT
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.util.Date;public class JwtGenerator {// 生成安全的密钥(仅示例,实际需妥善保管)private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);public static String generateToken(String userId, String role) {return Jwts.builder().setSubject(userId) // 主题(用户ID).claim("role", role) // 自定义声明:用户角色.setIssuedAt(new Date()) // 签发时间(默认当前时间).setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) // 过期时间(1小时后).signWith(SECRET_KEY) // 使用 HMAC-SHA256 算法签名,密钥为 SECRET_KEY.compact(); // 生成紧凑的 JWT 字符串}public static void main(String[] args) {String token = generateToken("user123", "admin");System.out.println("生成的 JWT: " + token);// 输出示例:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzE2NTYzMjAwLCJleHAiOjE3MTY1NjY4MDB9.xxx...}
}
二、解析并验证 JWT(提取内容)
通过 Jwts.parserBuilder()
方法创建一个 JWT 解析器(JwtParserBuilder
),设置验证参数(如密钥、算法),然后调用 parseClaimsJws(String jwt)
方法解析并验证 JWT。若验证通过,返回包含声明的 Claims
对象;若验证失败(如签名错误、已过期),则抛出异常。
关键步骤与方法
设置验证密钥和算法:
通过setSigningKey(Key key)
方法设置签名验证的密钥(需与生成 Token 时的密钥一致)。
若 Token 使用非对称算法(如 RSA),需设置公钥(setVerificationKey
)。可选配置(如忽略过期时间):
通过requireExpiration(false)
等方法调整验证策略(一般不建议忽略过期时间)。解析并验证:
调用parseClaimsJws(String jwt)
方法解析 Token,返回Jws<Claims>
对象,通过getBody()
获取声明(Claims
)。
示例:解析 JWT
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.security.Keys;
import java.security.Key;public class JwtParser {private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256); // 与生成时的密钥一致public static Claims parseToken(String token) {return Jwts.parserBuilder().setSigningKey(SECRET_KEY) // 设置验证密钥.build().parseClaimsJws(token) // 解析并验证 JWT.getBody(); // 获取声明内容}public static void main(String[] args) {String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzE2NTYzMjAwLCJleHAiOjE3MTY1NjY4MDB9.xxx..."; // 假设是生成的合法 Tokentry {Claims claims = parseToken(token);System.out.println("用户ID: " + claims.getSubject()); // 输出:user123System.out.println("角色: " + claims.get("role")); // 输出:adminSystem.out.println("过期时间: " + claims.getExpiration()); // 输出:过期时间戳} catch (Exception e) {System.out.println("Token 解析失败: " + e.getMessage()); // 签名错误、过期等场景会抛异常}}
}
在 Java 的 JWT(JSON Web Token)处理库 JJWT(Java JWT) 中,Jwts
是一个核心工具类,主要用于构建(生成)JWT 和解析(验证/读取)JWT。它本身是一个工厂类,提供静态方法返回 JwtBuilder
(构建器)或 JwtParser
(解析器)实例,实际功能由这些实例的方法实现。
三、核心方法分类
Jwts
的方法主要分为两类:构建 JWT 和 解析 JWT。
1. 构建 JWT(生成令牌)
通过 Jwts.builder()
获取 JwtBuilder
实例,用于设置 JWT 的声明(Claims)和签名,最终生成 JWT 字符串。
常用方法:
方法 | 说明 |
---|---|
Jwts.builder() | 工厂方法,返回一个 JwtBuilder 实例,用于开始构建 JWT。 |
JwtBuilder.setSubject(String subject) | 设置 JWT 的主题(sub 声明),通常为用户标识。 |
JwtBuilder.setIssuer(String issuer) | 设置 JWT 的颁发者(iss 声明)。 |
JwtBuilder.setAudience(String audience) | 设置 JWT 的接收者(aud 声明)。 |
JwtBuilder.setExpiration(Date expiration) | 设置 JWT 的过期时间(exp 声明,UTC 时间)。 |
JwtBuilder.setNotBefore(Date notBefore) | 设置 JWT 的生效时间(nbf 声明,UTC 时间)。 |
JwtBuilder.setId(String id) | 设置 JWT 的唯一标识(jti 声明),通常用于防重放攻击。 |
JwtBuilder.claim(String name, Object value) | 自定义声明(如 email 、role 等非标准声明)。 |
JwtBuilder.signWith(SignatureAlgorithm algorithm, Key key) | 指定签名算法(如 HS256 、RS256 )和密钥(对称或非对称),完成签名。 |
2. 解析 JWT(验证与读取)
通过 Jwts.parser()
获取 JwtParser
实例,用于验证 JWT 的签名并解析其声明。
常用方法:
方法 | 说明 |
---|---|
Jwts.parser() | 工厂方法,返回一个 JwtParser 实例,用于开始解析 JWT。 |
JwtParser.setSigningKey(Key key) | 设置签名验证的密钥(对称或非对称),必须与生成 JWT 时的密钥一致。 |
JwtParser.requireIssuer(String issuer) | 强制验证 JWT 的颁发者(iss 声明)必须等于指定值(可选校验)。 |
JwtParser.requireAudience(String audience) | 强制验证 JWT 的接收者(aud 声明)必须等于指定值(可选校验)。 |
Jws<Claims> parseClaimsJws(String jwt) | 解析并验证 JWT(带 JWS 签名),返回 Jws<Claims> 对象(包含头部和声明)。 |
Claims parseClaimsJwt(String jwt) | 解析 JWT(不验证签名,仅当已手动验证过时使用,不安全!)。 |
四、示例代码
生成 JWT(构建)
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.util.Date;// 生成密钥(实际生产环境应安全存储)
Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);String jws = Jwts.builder().setSubject("user123") // 主题.setIssuer("my-app") // 颁发者.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) // 1小时后过期.claim("role", "admin") // 自定义声明.signWith(key) // 签名(使用 HS256 算法和密钥).compact(); // 生成 JWT 字符串
解析 JWT(验证与读取)
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import java.security.Key;Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256); // 必须与生成时的密钥一致String jws = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwib3NfdXNlciI6Im15LWFwcCIsImV4cCI6MTY5MTYxNjAwMCwicm9sZSI6ImFkbWluIn0..."; // 实际 JWT// 解析并验证签名
var jwsClaims = Jwts.parser().setSigningKey(key).requireIssuer("my-app") // 强制验证颁发者.parseClaimsJws(jws);// 读取声明
String subject = jwsClaims.getBody().getSubject(); // "user123"
String role = jwsClaims.getBody().get("role", String.class); // "admin"
Date expiration = jwsClaims.getBody().getExpiration(); // 过期时间
五、注意事项
- 版本差异:JJWT 0.11.x 及以上版本(支持 Java 8+)与旧版本(0.x 早期)API 略有不同(如
Key
类型从byte[]
改为java.security.Key
),需根据版本调整代码。 - 签名验证:解析 JWT 时必须调用
signWith()
或setSigningKey()
验证签名,否则无法保证令牌未被篡改。 - 声明校验:推荐通过
requireIssuer()
、requireAudience()
等方法显式校验关键声明,避免使用未验证的令牌。 - 密钥安全:对称算法(如 HS256)的密钥需严格保密;非对称算法(如 RS256)需妥善管理公私钥对。
Jwts 支持的常见场景
- 单点登录(SSO):用户登录后生成 JWT,后续请求携带 JWT 完成身份验证。
- 接口鉴权:微服务间通过 JWT 传递用户权限信息,避免重复查询数据库。
- 无状态认证:服务端无需存储 Token,通过签名验证即可确认 Token 合法性。
注意事项
- 密钥安全:签名密钥(尤其是对称算法的密钥)需严格保密,泄露会导致 Token 被伪造。
- 算法选择:推荐使用安全的算法(如 HS256、RS256),避免使用已废弃的算法(如 HS384/HS512 需评估性能)。
- 声明的时效性:必须设置
exp
(过期时间),防止 Token 长期有效被劫持。 - 敏感信息避免明文:JWT 内容仅 Base64 编码(可解码),不要存储密码等敏感信息。
总结
Jwts
是 JJWT 库的核心工具类,主要用于生成和解析 JWT:
- 生成 Token:通过
Jwts.builder()
设置声明和签名,生成签名的 JWT 字符串。 - 解析 Token:通过
Jwts.parserBuilder()
验证签名并提取声明,确保 Token 合法性和数据完整性。
合理使用 Jwts
可以高效实现无状态认证、跨服务鉴权等场景,是 Java 中处理 JWT 的首选工具。