JWT
组成: header, payload,signature
header
头部包含两部分:声明类型和使用的哈希算法(通常直接使用HMAC SHA256,就是HS256)
payload
也称为JWT claims,放置需要传输的信息,有三类:
保留claims,主要包括iss发行者、exp过期时间、sub主题、aud用户等
公共claims,定义新创的信息,比如用户信息和其他重要信息
私有claims,用于发布者和消费者都同意以私有的方式使用的信息
JWT规定7个官方字段,供选用:
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
signature
需要采用编码的header、编码的payload、secret,使用header中指定的算法进行签名。
import com.allstar.cintracer.CinTracer;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.cmb.robot.data.common.BODConstant;
import com.util.crypto.U2OUtil;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtils {
private static final CinTracer tracer = CinTracer.getInstance(JwtUtils.class);
/**
* JWT user
*/
private static final String AUD = "LS37_COMMON_ROBOT_DATA";
/**
* token 过期时间: 10天
*/
public static final int CALENDAR_FIELD = Calendar.DATE;
public static final int CALENDAR_INTERVAL = 10;
/**
* JWT 密钥
*/
public static final String SECRET = "CMB-CHINA-XXXX";
/**
* JWT 唯一ID
*/
public static final String JTI = "CMB-XXXX";
public static String createToken(String openId, String username) {
String token = null;
try {
/**
* JWT header
* alg; use algorithm
* typ: token type
*/
Map<String, Object> header = new HashMap<>();
header.put("alg", "HS256");
header.put("typ", "JWT");
/**
* JWT payLoad
* 有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择。
* iss:发行人
* exp:到期时间
* sub:主题
* aud:用户
* nbf:在此之前不可用
* iat:发布时间
* jti:JWT ID用于标识该JWT
*
* 自定义私有字段
* "username": username
*/
Map<String, Object> payLoad = new HashMap<>();
payLoad.put("uid", openId);
payLoad.put("username", username);
payLoad.put("aud", AUD);
//JWT expire time
Calendar nowTime = Calendar.getInstance();
nowTime.add(CALENDAR_FIELD, CALENDAR_INTERVAL);
Date expiresDate = nowTime.getTime();
payLoad.put("exp", expiresDate);
payLoad.put("iat", new Date());
payLoad.put("jti", JTI);
/**
* JWT sign
* 签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改
*/
Algorithm sign = Algorithm.HMAC256(SECRET);
token = JWT.create()
.withHeader(header)
.withPayload(payLoad)
.withExpiresAt(expiresDate)
.sign(sign);
} catch (Exception e) {
tracer.error(BODConstant.BOD_402, BODConstant.BOD_100001, e, BODConstant.BOD_402_MSG, openId, username);
}
return token;
}
public static Map<String, Object> decode(String token) {
Map<String, Object> result = new HashMap<>();
try {
DecodedJWT decodedJWT = JWT
.require(Algorithm.HMAC256(SECRET))
.build()
.verify(token);
String openId = decodedJWT.getClaim("uid").asString();
String userName = decodedJWT.getClaim("username").asString();
tracer.special(BODConstant.BOD_403, U2OUtil.getUserId(openId), BODConstant.BOD_403_MSG, openId, userName);
result.put("uid", openId);
result.put("username", userName);
} catch (Exception e) {
tracer.error(BODConstant.BOD_400, BODConstant.BOD_100001, e, BODConstant.BOD_400_MSG, token);
}
return result;
}
}