diff --git a/src/main/java/com/yexuejc/base/util/JsonUtil.java b/src/main/java/com/yexuejc/base/util/JsonUtil.java index 2026c45..7c42672 100644 --- a/src/main/java/com/yexuejc/base/util/JsonUtil.java +++ b/src/main/java/com/yexuejc/base/util/JsonUtil.java @@ -252,7 +252,7 @@ public class JsonUtil { /** * Json字符串转换为Java对象 * - * @param in 输入流 + * @param in 输入流 * @param parametrized 容器类 * @param parameterClasses 实际类 * @return @@ -347,6 +347,30 @@ public class JsonUtil { return json2Obj(obj2Json(pojo), Map.class); } + /** + * json -> Map 转换 + * + * @param json JSON + * @return Map + */ + public static Map jsonToMapString(String json) { + return objToMap(json, String.class, String.class); + } + + /** + * 将 Bean 对象转换为 Map + *

+ * 示例:Map map = JacksonMapperConfig.objToMap(data, String.class, RequestBean.class); + *

+ * + * @param pojo Bean 数据 + * @return Map 数据 + */ + + public static Map objToMap(Object pojo, Class kCls, Class vCls) { + return json2Obj(obj2Json(pojo), Map.class, kCls, vCls); + } + /** * 格式化输出 * diff --git a/src/main/java/com/yexuejc/base/util/JwtUtil.java b/src/main/java/com/yexuejc/base/util/JwtUtil.java index fdd1cdf..4fee650 100644 --- a/src/main/java/com/yexuejc/base/util/JwtUtil.java +++ b/src/main/java/com/yexuejc/base/util/JwtUtil.java @@ -1,12 +1,14 @@ package com.yexuejc.base.util; +import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.Map; import javax.crypto.SecretKey; +import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SecureDigestAlgorithm; /** * jwt工具类 @@ -34,35 +36,46 @@ public class JwtUtil { /** * 参数配置:设置一次即可,多次设置会覆盖之前的 * - * @param key 加密key 默认:h%OG8Y3WgA5AN7&6Ke7I#C1XvneW0N8a - * @param type 加密类型:默认JWT - * @param iss token发行商: 默认yexuejc.top + * @param type 加密类型:默认JWT + * @param iss token发行商: 默认yexuejc.top + * @param key 加密key 默认:h%OG8Y3WgA5AN7&6Ke7I#C1XvneW0N8a + * @param algorithm 加密方式 * @return */ - public static JwtUtil config(String key, String type, String iss) { + public static JwtUtil config(String type, String iss, String key, SecureDigestAlgorithm algorithm) { JwtUtil jwtUtil = instace(); - jwtUtil.JWT_SIGNATURE_KEY = key; - jwtUtil.JWT_HEADER_TYP = type; - jwtUtil.JWT_CLAIMS_ISS = iss; + if (null != key) { + jwtUtil.jwtSignatureKey = key; + } + if (null != type) { + jwtUtil.jwtHeaderTyp = type; + } + if (null != iss) { + jwtUtil.jwtClaimsIss = iss; + } + if (null != algorithm) { + jwtUtil.algorithm = algorithm; + } return jwtUtil; } - public static class Instace { + private static class Instace { private static JwtUtil jwtUtil = new JwtUtil(); } /** * 加密用KEY */ - private String JWT_SIGNATURE_KEY = "h%OG8Y3WgA5AN7&6Ke7I#C1XvneW0N8a"; + private String jwtSignatureKey = "h%OG8Y3WgA5AN7&6Ke7I#C1XvneW0N8a"; /** * token类型 */ - private String JWT_HEADER_TYP = "JWT"; + private String jwtHeaderTyp = "JWT"; /** * token发行商 */ - private String JWT_CLAIMS_ISS = "yexuejc.top"; + private String jwtClaimsIss = "yexuejc.top"; + private SecureDigestAlgorithm algorithm = Jwts.SIG.HS512; /** * 加密内容生成token @@ -71,27 +84,36 @@ public class JwtUtil { * @return */ public String compact(Object subjectObj) { - String subject = null; - if (subjectObj instanceof String) { - subject = (String) subjectObj; - } else { - subject = JsonUtil.obj2Json(subjectObj); + return compact(null, subjectObj); + } + + public String compact(String subId, Object subjectObj) { + String subject = subId; + Map subMap = JsonUtil.objToMap(subjectObj, String.class, Object.class); + if (StrUtil.isEmpty(subject)) { + if (subjectObj instanceof String) { + subject = (String) subjectObj; + } else if (StrUtil.isNotEmpty(subMap)) { + Object sid = subMap.get("subId"); + Object s = subMap.get("sub"); + subject = StrUtil.isNotEmpty(sid) ? String.valueOf(sid) : String.valueOf(s); + } } + Date now = new Date(); return Jwts.builder() // 设置token的唯一标识ID(claims.jti) .id(StrUtil.genUUID()) // 设置token类型(header.typ) - .header().add("typ", JWT_HEADER_TYP) - .and() + .header().add("typ", jwtHeaderTyp).and() // 设置token发行时间为当前时间(claims.iat) - .issuedAt(now) + .issuedAt(now).claims(JsonUtil.objToMap(subjectObj, String.class, Object.class)) // 设置token发行商/发行者(claims.iss) - .issuer(JWT_CLAIMS_ISS) + .issuer(jwtClaimsIss) // 设置token用户定义主体(claims.sub) .subject(subject) // 设置算法签名,(密钥,加密算法) - .signWith(getSecretKey(), Jwts.SIG.HS512) + .signWith(getSecretKey(), algorithm) // 生成token .compact(); } @@ -114,20 +136,27 @@ public class JwtUtil { * @return */ public T parse(String token, Class cls) { - return JsonUtil.json2Obj(parseStr(token), cls); + return JsonUtil.json2Obj(JsonUtil.obj2Json(parseStr(token)), cls); } + /** * 解密token为字符串 * * @param token * @return */ - public String parseStr(String token) { - return Jwts.parser().verifyWith(getSecretKey()).build().parseSignedClaims(token).getPayload().getSubject(); + public Claims parseStr(String token) { + return Jwts.parser().verifyWith(getSecretKey()).build().parseSignedClaims(token).getPayload(); } private SecretKey getSecretKey() { - byte[] bytes = Decoders.BASE64.decode(JWT_SIGNATURE_KEY); + int minLen = 32; + if (jwtSignatureKey.length() % minLen != 0) { + // 补齐32的倍数,左补0 + String format = "%" + ((jwtSignatureKey.length() / minLen + 1) * minLen) + "s"; + jwtSignatureKey = String.format(format, jwtSignatureKey).replace(' ', '0'); + } + byte[] bytes = jwtSignatureKey.getBytes(StandardCharsets.UTF_8); return Keys.hmacShaKeyFor(bytes); } } diff --git a/src/test/java/com/yexuejc/base/util/JwtUtilTest.java b/src/test/java/com/yexuejc/base/util/JwtUtilTest.java new file mode 100644 index 0000000..beeb6b0 --- /dev/null +++ b/src/test/java/com/yexuejc/base/util/JwtUtilTest.java @@ -0,0 +1,26 @@ +package com.yexuejc.base.util; + +import java.util.Map; + +import io.jsonwebtoken.Jwts; +import org.junit.jupiter.api.Test; + +/** + * @author maxiaofeng + * @date 2024/9/1 15:23 + */ +class JwtUtilTest { + + @Test + void compact() { + Map map = JsonUtil.json2Obj("{\n" + " \"payload\": {\n" + " \"sub\": \"0fqgx9h1d9eijd07umlyn1ez52jvkkkb883j\",\n" + " " + + "\"iss\": \"www" + ".donki.com\",\n" + " \"aud\": \"D27A80C9AF01488F9A1152B8C20D93BA\",\n" + " \"exp\": 1725260806," + + "\n" + " " + "\"iat\": 1725174406,\n" + " \"address\": {\n" + " \"country\": \"南朝鮮\"\n" + " },\n" + " " + "\"email_verified\": true,\n" + " \"birthdate\": \"1993/11/16\",\n" + " \"news_letter\": \"1\",\n" + " " + "\"gender\": \"other\",\n" + " \"member_code\": \"3511623793483553889787\",\n" + " \"preferred_username\": " + "\"3923490434\",\n" + " \"nonce\": \"mjhjSTmtVRNWPBtOQXZx\",\n" + " \"country_code\": \"CHN\",\n" + " " + "\"language_code\": \"zh-TW\",\n" + " \"updated_at\": 1722404351,\n" + " \"nickname\": \"3923490434\",\n" + " " + "\"customer_flag\": \"0\",\n" + " \"service_term_version\": \"2\",\n" + " \"email\": \"1828844769@qq.com\",\n" + " " + " \"auth_time\": 1725173983\n" + " }\n" + "}", Map.class); + JwtUtil jwtUtil = JwtUtil.config("JWT", "www.donki.com", "5326D79EDEF344C3B3431F268DD2564C", Jwts.SIG.HS256); + String jwtStr = jwtUtil.compact(map.get("payload")); + System.out.println(jwtStr); + + Map parse = jwtUtil.parse(jwtStr); + System.out.println(JsonUtil.obj2Json(parse)); + } +} \ No newline at end of file