package com.llwx.common.utils;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.llwx.common.bean.UserMerchantInfo;
import com.llwx.common.enums.ResponseCodeEnum;
import com.llwx.common.exceptions.BizCheckedException;
/**
* tokenUtil
*
*/
public class TokenUtil {
private static final String SUB = "session";
private static final String ISSUER = "llwx";
private static final String PHONE = "phone";
private static final String MERCHANT_ID = "merchant_id";
/**
* 校验 token 是否合法
*
* @param token token
* @param secret 密钥
*/
public static void verifyToken(String token, String secret) throws JWTVerificationException, BizCheckedException {
try {
Algorithm algorithm = Algorithm.HMAC256(secret);
DecodedJWT decodeJwt = JWT.decode(token);
String userId = decodeJwt.getAudience()
.get(0);
String phone = decodeJwt.getClaim(PHONE)
.asString();
String merchantId = decodeJwt.getClaim(MERCHANT_ID)
.asString();
// 校验签名是否符合客户端告知的用户信息
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer(ISSUER)
.withSubject(SUB)
.withAudience(userId)
.withClaim(PHONE, phone)
.withClaim(MERCHANT_ID, merchantId)
.build();
DecodedJWT jwt = verifier.verify(token);
Date expiresAt = jwt.getExpiresAt();
String expiresAtStr = DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(expiresAt);
if (expiresAt.before(new Date())) {
throw new BizCheckedException(ResponseCodeEnum.TOKEN_INVALID.getCode(),
String.format("用户 %s 的登录已过期。过期时间 %s", userId, expiresAtStr));
}
} catch (Exception e) {
throw new BizCheckedException(e, ResponseCodeEnum.TOKEN_INVALID.getCode(),
ResponseCodeEnum.TOKEN_INVALID.getMsg());
}
}
public static UserMerchantInfo getUserMerchantInfo(String token) {
String userId = getUserId(token);
String phone = getPhone(token);
String merchantId = getMerchantId(token);
UserMerchantInfo userMerchantInfo = new UserMerchantInfo();
userMerchantInfo.setMerchantId(merchantId);
userMerchantInfo.setOpenId(userId);
userMerchantInfo.setPhone(phone);
return userMerchantInfo;
}
/**
* 解析 token 获取用户 userId
*
* @param token tk
* @return userId
*/
public static String getUserId(String token) {
DecodedJWT jwt = JWT.decode(token);
return jwt.getAudience()
.get(0);
}
/**
* 解析 token 获取用户 userId
*
* @param token tk
* @return userId
*/
public static String getPhone(String token) {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim(PHONE)
.asString();
}
/**
* 解析 token 获取用户 userId
*
* @param token tk
* @return userId
*/
public static String getMerchantId(String token) {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim(MERCHANT_ID)
.asString();
}
/**
* 创建 jwt token
*
* @param secret 密钥
* @param outMinutes 过期时间
* @return token
*/
public static String createToken(String secret, long outMinutes, String userId, String phone, String merchantId) {
Algorithm al = Algorithm.HMAC256(secret);
Instant instant = LocalDateTime.now()
.plusMinutes(outMinutes)
.atZone(ZoneId.systemDefault())
.toInstant();
Date expire = Date.from(instant);
return JWT.create()
.withIssuer(ISSUER)
.withSubject(SUB)
.withAudience(userId)
.withClaim(PHONE, phone)
.withClaim(MERCHANT_ID, merchantId)
.withExpiresAt(expire)
.sign(al);
}
}