加载依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
载荷对象
JWT中,会保存载荷数据,我们计划存储3部分:
- id:jwt的id
- 用户信息:用户数据,不确定,可以是任意类型
- 过期时间:Date
为了方便后期获取,我们定义一个类来封装:
import lombok.Data;
import java.util.Date;
@Data
public class Payload<T> {
private String id;
private T userInfo;
private Date expiration;
}
封装载荷类中的用户信息:UserInfo
这里我们假设用户信息包含3部分:
- id:用户id
- username:用户名
- role:角色(权限中会使用)
载荷:UserInfo
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
//用户id
private Long id;
//username:用户名
private String username;
//角色(权限中会使用)
private String role;
}
工具类
import com.leyou.common.auth.pojo.Payload;
import com.leyou.common.utils.JsonUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import java.util.UUID;
public class JwtUtils {
private static final String JWT_PAYLOAD_USER_KEY = "user";
/**
* 私钥加密token
*
* @param userInfo 载荷中的数据
* @param privateKey 私钥
* @param expire 过期时间,单位分钟
* @return JWT
*/
public static String generateTokenExpireInMinutes(Object userInfo, PrivateKey privateKey, int expire) {
return Jwts.builder()
.claim(JWT_PAYLOAD_USER_KEY, JsonUtils.toString(userInfo))
.setId(createJTI())
.setExpiration(DateTime.now().plusMinutes(expire).toDate())
.signWith(privateKey, SignatureAlgorithm.RS256)
.compact();
}
/**
* 私钥加密token
*
* @param userInfo 载荷中的数据
* @param privateKey 私钥
* @param expire 过期时间,单位秒
* @return JWT
*/
public static String generateTokenExpireInSeconds(Object userInfo, PrivateKey privateKey, int expire) {
return Jwts.builder()
.claim(JWT_PAYLOAD_USER_KEY, JsonUtils.toString(userInfo))
.setId(createJTI())
.setExpiration(DateTime.now().plusSeconds(expire).toDate())
.signWith(privateKey, SignatureAlgorithm.RS256)
.compact();
}
/**
* 公钥解析token
*
* @param token 用户请求中的token
* @param publicKey 公钥
* @return Jws<Claims>
*/
private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
}
private static String createJTI() {
return new String(Base64.getEncoder().encode(UUID.randomUUID().toString().getBytes()));
}
/**
* 获取token中的用户信息
*
* @param token 用户请求中的令牌
* @param publicKey 公钥
* @return 用户信息
*/
public static <T> Payload<T> getInfoFromToken(String token, PublicKey publicKey, Class<T> userType) {
Jws<Claims> claimsJws = parserToken(token, publicKey);
Claims body = claimsJws.getBody();
Payload<T> claims = new Payload<>();
claims.setId(body.getId());
claims.setUserInfo(JsonUtils.toBean(body.get(JWT_PAYLOAD_USER_KEY).toString(), userType));
claims.setExpiration(body.getExpiration());
return claims;
}
/**
* 获取token中的载荷信息
*
* @param token 用户请求中的令牌
* @param publicKey 公钥
* @return 用户信息
*/
public static <T> Payload<T> getInfoFromToken(String token, PublicKey publicKey) {
Jws<Claims> claimsJws = parserToken(token, publicKey);
Claims body = claimsJws.getBody();
Payload<T> claims = new Payload<>();
claims.setId(body.getId());
claims.setExpiration(body.getExpiration());
return claims;
}
}
测试
//生成jwt的token
//公钥本地的位置
private String pubkeyPath = "F:\\rsa_key\\rsa_key.pub";
//私钥本地的位置
private String prikeyPath = "F:\\rsa_key\\rsa_key";
@Test
public void generateToken() throws Exception {
UserInfo userInfo = new UserInfo(1l,"aaaa","管理员");
PrivateKey privateKey = RsaUtils.getPrivateKey(prikeyPath);
//生成token
String token = JwtUtils.generateTokenExpireInMinutes(userInfo, privateKey, 5);
System.out.println("token = " + token);
}
//解析token
@Test
public void parseToken() throws Exception {
//上面生成的
String token = "eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyIjoie1wiaWRcIjoxLFwidXNlcm5hbWVcIjpcIkF1Z" +
"2FhYVwiLFwicm9sZVwiOlwi566h55CG5ZGYXCJ9IiwianRpIjoiWkRBM05EazJZek10WVdNeU5pMDBNekJ" +
"tTFRsaU0ySXRPVGMwWXpnMk9HWTNPVGsyIiwiZXhwIjoxNTg5NTUyOTAzfQ.Q91lhYLxPP53xBMYZ67pcR" +
"7k29CmXqPihokQnw9aRfgIXG1IJ_-1Xt4nCMqRrgJ9Gph8WynAjXEys55LEM4NYG9m_fwqDT3WOuNhcQ-w" +
"TYxTT6gRFhLDYcF22cdL0JF0jMCBt9e5PA6gSAqn848hQjzLV-s1B_yuF3u4zpq2BiBtsZy-tGzIkahjlz-" +
"68UTkzJJIfnzsNrGlqFx2TmYwggI-s0agYgVu1_tm0QBThYBh8H8aiu9kj9ghjScLq5OOT0sGZ22OaffUVeu" +
"F1a5FLpVEuhhOpctv4gN6oEfz8AtWB20gtEsEpcPbtGiL1vPXfkYn18lJ4aoo2LCh1F_5ww";
//公钥
PublicKey publicKey = RsaUtils.getPublicKey(pubkeyPath);
//得到载荷对象
Payload<UserInfo> infoFromToken = JwtUtils.getInfoFromToken(token, publicKey, UserInfo.class);
//得到载荷对象中的用户信息
UserInfo userInfo = infoFromToken.getUserInfo();
System.out.println(userInfo);
System.out.println(infoFromToken.getId());
System.out.println(infoFromToken.getExpiration());
}