package com.yunzhi.demo.common; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; import lombok.extern.slf4j.Slf4j; import javax.crypto.SecretKey; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Base64; import java.util.Date; import java.util.Map; /** * JWTUtils * jwt 辅助类 * https://github.com/jwtk/jjwt */ @Slf4j public class JWTUtils { // 过期时间 30 分钟 public static final long EXPIRE_TIME = 30 * 60; // 私钥 static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(Base64.getEncoder().encode("Yansen is so handsome. He is a good man. Everyone like him !!!".getBytes())); // 请求头 public static final String AUTH_HEADER = "X-Authorization-JWT"; /** * 生成 token, claims 里必须要有 userId * @param claims * @return */ public static String encode(Map claims) { Date[] datePair = getDatePair(); Date iat = datePair[0]; Date exp = datePair[1]; return Jwts.builder().setIssuer(claims.get("userId").toString()).setIssuedAt(iat).setExpiration(exp).addClaims(claims).signWith(SECRET_KEY).compact(); } public static Map decode(String token) throws Exception { return parse(token); } public static String refresh(String token) { try { Claims claims = parse(token); Integer iat = (Integer) claims.get("iat"); if (null != iat) { long currentTime = System.currentTimeMillis() / 1000; int oneMinute = 60; if (currentTime - iat < oneMinute) { return token; } } claims.remove("iat"); claims.remove("exp"); return encode(claims); } catch (Exception e) { log.error("解析 JWT Token 失败: {}", e.getMessage()); } return null; } public static void refresh(String jws, HttpServletResponse response) { if (!StringUtils.isEmpty(jws)) { String token = refresh(jws); response.addHeader(AUTH_HEADER, token); } } public static String getToken(HttpServletRequest request) { return request.getHeader(AUTH_HEADER); } public static void verify(String token) throws Exception { parse(token); } private static Date[] getDatePair() { LocalDateTime now = LocalDateTime.now(); Date iat = Date.from(now.atZone(ZoneId.systemDefault()).toInstant()); Date exp = Date.from(now.plusSeconds(EXPIRE_TIME).atZone(ZoneId.systemDefault()).toInstant()); return new Date[]{iat, exp}; } private static Claims parse(String token) throws Exception { if (token == null || "".equals(token)) { throw new Exception("Token 不能为空"); } long skew = 5; Jws claimsJws = Jwts.parserBuilder().setAllowedClockSkewSeconds(skew).setSigningKey(SECRET_KEY).build().parseClaimsJws(token); return claimsJws.getBody(); } }