1、JWT的组成结构
JWT由三部分组成:
- 标头(header)
- 有效载荷(payload)
- 签名(signature)
1.1、header
header 由两部分组成:令牌的类型(JWT)和签名所使用的算法。它使用 Base64 编码组成
注意:Base64 不是加密算法,所以 header 是没有加密的
1.2、payload
payload 用来存放实际需要传递的数据,同样使用 Base64 编码组成
JWT 规定了7个官方字段:
- iss(issuer):签发人
- exp(expiration time):过期时间
- sub(subject):主题
- aud(audience):受众
- nbf(Not Before):生效时间
- iat(Issued At):签发时间
- jti(JWT ID):编号
其他数据使用 withClain 存放
注意:Base64 不是加密算法,所以 header 是没有加密的,不建议放敏感信息
1.3、signature
signature 使用编码后的 header 和 payload 以及一个密钥,使用指定的加密算法进行加密。
签名的作用是保证 JWT 没有被篡改过
2、引入依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.1</version>
</dependency>
3、JWT的使用
3.1、生成Token
Calendar instance = Calendar.getInstance();
instance.add(Calendar.MINUTE, 2);
// 生成令牌
String token = JWT.create()
.withClaim("userId", 123) // payload
.withClaim("username", "张三")
.withExpiresAt(instance.getTime()) // 过期时间
.sign(Algorithm.HMAC256("dasjj126341")); // 加密算法及密钥
3.2、解析Token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("dasjj126341")).build();
DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzA5MTQ5ODEsInVzZXJJZCI6MTIzLCJ1c2VybmFtZSI6IuW8oOS4iSJ9.8DB2zK7nMGCRrPNqSlvRmH8vKdhTvFFbfHMgCVlZWo8");
System.out.println(verify.getClaim("userId"));
System.out.println(verify.getClaim("username"));
3.3、常见异常信息
- SignatureVerificationException: 签名不一致异常
- TokenExpiredException: 令牌过期异常
- AlgorithmMismatchException: 算法不匹配异常
- InvalidClaimException: 失效的payload异常
4、封装工具类
public class JWTUtils {
/**
* 密钥
*/
private static final String SIGN = "ju!aSWWd23@4";
/**
* @param map : 写入payload中的数据
* @return : token
*/
public static String getToken(Map<String, String> map) {
// 默认7天
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, 7);
// payload
JWTCreator.Builder tokenBuilder = JWT.create();
map.forEach(tokenBuilder::withClaim);
tokenBuilder.withExpiresAt(instance.getTime());
return tokenBuilder.sign(Algorithm.HMAC256(SIGN));
}
/**
* @param map : 写入payload中的数据
* @param day : token过期天数
* @return : token
*/
public static String getToken(Map<String, String> map, int day) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, day);
// payload
JWTCreator.Builder tokenBuilder = JWT.create();
map.forEach(tokenBuilder::withClaim);
tokenBuilder.withExpiresAt(instance.getTime());
return tokenBuilder.sign(Algorithm.HMAC256(SIGN));
}
/**
* 获取token信息
* @param token :
* @return : token信息
*/
public static DecodedJWT verify(String token) {
return JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
}
}