From 77ff5c4cfc7532a63f1ad84ddc5ee513be87ccaf Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Fri, 31 May 2024 14:53:52 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat(=E4=BF=AE=E6=94=B9):=20:bug:=20JWT?= =?UTF-8?q?=E6=AF=8F=E6=AC=A1=E7=94=9F=E6=88=90=E9=83=BD=E4=B8=80=E6=A0=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/service-utils/pom.xml | 6 + .../bunny/common/service/utils/JwtHelper.java | 287 +++++++++++++++++- .../gateway/controller/IndexController.java | 2 +- .../admin/controller/IndexController.java | 2 +- .../web/controller/IndexController.java | 2 +- .../test/java/cn/bunny/jwt/JwtHelperTest.java | 122 ++++++++ 6 files changed, 410 insertions(+), 11 deletions(-) create mode 100644 service/service-web/src/test/java/cn/bunny/jwt/JwtHelperTest.java diff --git a/common/service-utils/pom.xml b/common/service-utils/pom.xml index 0405330..ad64f54 100644 --- a/common/service-utils/pom.xml +++ b/common/service-utils/pom.xml @@ -28,6 +28,12 @@ httpclient 4.5.14 + + + javax.xml.bind + jaxb-api + 2.3.1 + com.github.xiaoymin diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java index cbce3e2..1f5e5d4 100644 --- a/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java @@ -4,22 +4,264 @@ import io.jsonwebtoken.*; import org.springframework.util.StringUtils; import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; public class JwtHelper { + // 时间 按天 计算 private static final long tokenExpiration = 24 * 60 * 60 * 1000; + // JWT 的 秘钥 private static final String tokenSignKey = "Bunny-Java-Template"; + // 默认主题 + private static final String subject = "Bunny"; + // 默认时间 + private static final Date time = new Date(System.currentTimeMillis() + tokenExpiration * 7); - public static String createToken(Long userId, String userName, Integer day) { + /** + * 使用默认主题,默认时间,默认秘钥,创建自定义集合token + * + * @param map 集合 + * @return token + */ + public static String createTokenWithMap(Map map) { return Jwts.builder() - .setSubject("Bunny-USER") + .setSubject(subject) + .setExpiration(time) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 使用默认主题,默认秘钥,自定义时间,创建集合形式token + * + * @param map 集合 + * @param time 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, Date time) { + return Jwts.builder() + .setSubject(subject) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .setExpiration(time) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 使用默认主题,默认秘钥,自定义时间,创建集合形式token + * + * @param map 集合 + * @param day 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, Integer day) { + return Jwts.builder() + .setSubject(subject) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * day)) - .claim("userId", userId) - .claim("userName", userName) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 使用默认主题,默认秘钥,自定义key,创建集合形式token + * + * @param map 集合 + * @param tokenSignKey 自定义key + * @return token + */ + public static String createTokenWithMap(Map map, String tokenSignKey) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(time) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 使用自定义主题,自定义时间,创建集合形式token + * + * @param map 集合 + * @param subject 主题 + * @param time 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String subject, Date time) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(time) + .setClaims(map) + .setId(UUID.randomUUID().toString()) .signWith(SignatureAlgorithm.HS256, tokenSignKey) .compressWith(CompressionCodecs.GZIP) .compact(); } + /** + * 创建集合形式token + * + * @param map 集合 + * @param subject 主题 + * @param tokenSignKey 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String subject, String tokenSignKey) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(time) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 创建集合形式token + * + * @param map 集合 + * @param tokenSignKey 主题 + * @param time 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String tokenSignKey, Integer time) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * time)) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .compressWith(CompressionCodecs.GZIP) + .compact(); + } + + /** + * 创建集合形式token + * + * @param map 集合 + * @param subject 主题 + * @param day 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String subject, String tokenSignKey, Integer day) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * day)) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .compressWith(CompressionCodecs.GZIP) + .compact(); + } + + /** + * 创建集合形式token + * + * @param map 集合 + * @param subject 主题 + * @param time 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String subject, String tokenSignKey, Date time) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(time) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .compressWith(CompressionCodecs.GZIP) + .compact(); + } + + /** + * 根据用户名和ID创建token + * + * @param userId 用户ID + * @param userName 用户名 + * @param day 过期时间 + * @return token值 + */ + public static String createToken(Long userId, String userName, Integer day) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * day)) + .claim("userId", userId) + .claim("userName", userName) + .setId(UUID.randomUUID().toString()) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .compressWith(CompressionCodecs.GZIP) + .compact(); + } + + /** + * 使用token获取map集合,使用默认秘钥 + * + * @param token token + * @return map集合 + */ + public static Map getTokenByMap(String token) { + if (!StringUtils.hasText(token)) return null; + Claims claims = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody(); + + // 将 body 值转为map + return new HashMap<>(claims); + } + + /** + * 使用token获取map集合 + * + * @param token token + * @param signKey 秘钥 + * @return map集合 + */ + public static Map getTokenByMap(String token, String signKey) { + if (!StringUtils.hasText(token)) return null; + Jws claimsJws = Jwts.parser().setSigningKey(signKey).parseClaimsJws(token); + Claims body = claimsJws.getBody(); + // 将 body 值转为map + return new HashMap<>(body); + } + + /** + * 根据token获取主题 + * + * @param token token + * @return 主题 + */ + public static String getTokenBySubject(String token) { + if (!StringUtils.hasText(token)) return null; + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Claims body = claimsJws.getBody(); + + return body.getSubject(); + } + + /** + * 根据token获取主题 + * + * @param token token + * @return 主题 + */ + public static String getTokenBySubject(String token, String tokenSignKey) { + if (!StringUtils.hasText(token)) return null; + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Claims body = claimsJws.getBody(); + + return body.getSubject(); + } + + /** + * 根据token获取用户ID + * + * @param token token + * @return 用户ID + */ public static Long getUserId(String token) { if (!StringUtils.hasText(token)) return null; @@ -29,6 +271,12 @@ public class JwtHelper { return Long.valueOf(String.valueOf(claims.get("userId"))); } + /** + * 根据token获取用户名 + * + * @param token token + * @return 用户名 + */ public static String getUsername(String token) { if (!StringUtils.hasText(token)) return ""; @@ -37,14 +285,37 @@ public class JwtHelper { return (String) claims.get("userName"); } - public static void removeToken(String token) { - // jwttoken无需删除,客户端扔掉即可。 + /** + * 判断token是否过期 + * + * @param token token + * @return 是否过期 + */ + public static boolean isExpired(String token) { + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Date expiration = claimsJws.getBody().getExpiration(); + + return expiration != null && expiration.before(new Date()); + } + + /** + * 判断token是否过期 + * + * @param token token + * @return 是否过期 + */ + public static boolean isExpired(String token, String tokenSignKey) { + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Date expiration = claimsJws.getBody().getExpiration(); + + return expiration != null && expiration.before(new Date()); } public static void main(String[] args) { String token = JwtHelper.createToken(7L, "admin", 7); + System.out.println(token); // token = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_6tWKi5NUrJScirNy6vUDQ12DVLSUUqtKFCyMjQ3MTc0NrYwNddRKi1OLfJMUbKyNDIwNLQwMDAzg4j5JeamAjUbGhtaWhoYGJqaOBQW6iXn5yrVAgCrO9jLWAAAAA.DS1wYprXGoIMrjtUWfDSN9AG5gWoRZ17oAgcvC0kwag"; - System.out.println(JwtHelper.getUserId(token)); - System.out.println(JwtHelper.getUsername(token)); + // System.out.println(JwtHelper.getUserId(token)); + // System.out.println(JwtHelper.getUsername(token)); } } \ No newline at end of file diff --git a/server-gateway/src/main/java/cn/bunny/service/gateway/controller/IndexController.java b/server-gateway/src/main/java/cn/bunny/service/gateway/controller/IndexController.java index 6922ee4..86c4109 100644 --- a/server-gateway/src/main/java/cn/bunny/service/gateway/controller/IndexController.java +++ b/server-gateway/src/main/java/cn/bunny/service/gateway/controller/IndexController.java @@ -11,6 +11,6 @@ import org.springframework.web.bind.annotation.RestController; public class IndexController { @GetMapping() public String index() { - return "欢迎访问 Bunny Template 网关服务"; + return "欢迎访问 Bunny Template 网关服务 微服务模板 欢迎去Gitee:https://gitee.com/BunnyBoss/java-mirror-server.git"; } } diff --git a/service/service-admin/src/main/java/cn/bunny/service/admin/controller/IndexController.java b/service/service-admin/src/main/java/cn/bunny/service/admin/controller/IndexController.java index 1245ba5..937bf56 100644 --- a/service/service-admin/src/main/java/cn/bunny/service/admin/controller/IndexController.java +++ b/service/service-admin/src/main/java/cn/bunny/service/admin/controller/IndexController.java @@ -8,6 +8,6 @@ import org.springframework.web.bind.annotation.RestController; public class IndexController { @RequestMapping("") public String index() { - return "欢迎访问BunnyBBS"; + return "欢迎访问 Bunny Template 微服务模板 欢迎去Gitee:https://gitee.com/BunnyBoss/java-mirror-server.git"; } } diff --git a/service/service-web/src/main/java/cn/bunny/service/web/controller/IndexController.java b/service/service-web/src/main/java/cn/bunny/service/web/controller/IndexController.java index 7588cd8..aa415c4 100644 --- a/service/service-web/src/main/java/cn/bunny/service/web/controller/IndexController.java +++ b/service/service-web/src/main/java/cn/bunny/service/web/controller/IndexController.java @@ -11,6 +11,6 @@ import org.springframework.web.bind.annotation.RestController; public class IndexController { @GetMapping("") public String index() { - return "欢迎访问 Bunny Template 微服务模板"; + return "欢迎访问 Bunny Template 微服务模板 欢迎去Gitee:https://gitee.com/BunnyBoss/java-mirror-server.git"; } } diff --git a/service/service-web/src/test/java/cn/bunny/jwt/JwtHelperTest.java b/service/service-web/src/test/java/cn/bunny/jwt/JwtHelperTest.java new file mode 100644 index 0000000..edaf1f1 --- /dev/null +++ b/service/service-web/src/test/java/cn/bunny/jwt/JwtHelperTest.java @@ -0,0 +1,122 @@ +package cn.bunny.jwt; + +import cn.bunny.common.service.utils.JwtHelper; +import cn.bunny.entity.system.user.User; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import org.junit.jupiter.api.Test; + +import java.util.Date; +import java.util.Map; + +class JwtHelperTest { + private static final String key = "my-key"; + private static final String subject = "my-subject"; + + private static Map getMap() { + User user = new User(); + user.setId(123L); + user.setAvatar("http://129.211.31.58:4000/#/chat"); + user.setEmail("user@example.com"); + user.setNickName("user@example.com"); + + // 将对象转为map + Map map = JSONObject.parseObject(JSONArray.toJSONString(user), Map.class); + return map; + } + + @Test + void createTokenWithMap() { + // 自定义 天数过期 + String token = JwtHelper.createTokenWithMap(getMap()); + System.out.println(token); + } + + @Test + void testCreateTokenWithMap() { + // 自定义key + String token = JwtHelper.createTokenWithMap(getMap(), new Date(System.currentTimeMillis() + 666666)); + System.out.println(token); + } + + @Test + void createTokenWithMap0() { + // 自定义 天数过期 + String token = JwtHelper.createTokenWithMap(getMap(), 1); + System.out.println(token); + } + + @Test + void testCreateTokenWithMap1() { + // 自定义 天数过期 + String token = JwtHelper.createTokenWithMap(getMap(), key); + System.out.println(token); + } + + @Test + void testCreateTokenWithMap2() { + // 自定义 天数过期 + String token = JwtHelper.createTokenWithMap(getMap(), subject, key); + System.out.println(token); + } + + @Test + void testCreateTokenWithMap3() { + // 自定义 天数过期 + String token = JwtHelper.createTokenWithMap(getMap(), subject, 7); + System.out.println(token); + } + + @Test + void createToken1() { + // 自定义 天数过期 + String token = JwtHelper.createTokenWithMap(getMap(), subject, new Date()); + System.out.println(token); + } + + @Test + void createToken2() { + // 自定义 天数过期 + String token = JwtHelper.createTokenWithMap(getMap(), subject, key, new Date()); + System.out.println(token); + } + + @Test + void createToken3() { + // 自定义 天数过期 + String token = JwtHelper.createTokenWithMap(getMap(), subject, key, 1); + System.out.println(token); + } + + @Test + void getTokenByMap() { + // createTokenWithMap 的 token + String createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MQQqAIBBA0btM21BHC8pVVxlsIClNzCKI7p4HaP_ffyB6t0YKDBbOg_PEN4W0sXB7gBb8DBa1aYEuKpRrtJSSrJSoR6ERhUHRD7ZTSslGuoVKRRzIb3-_9wN8w_-EbwAAAA.WFmbbjfwGycJp6-Ak8uoYdIO0R8brA8rmh5ZrG1kawI"; + createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ6DIBBA4btMt_IzKgqseoLeYQSMtGKJpU0T493LAbr-Xt4BmXZKYI-zgS26x41SAAvvV9iv4Uspr4G7Z4IG6EOF9mpLKdkKga3hLSLvkCtteymluAi3UKlt9GCx7RoIieL6_3cvscI8T1orRwydUazHwTOj1cAmrzTSOKoRNZw_Uq-ijacAAAA.kOxzGz-821wJo-hRJ2FRZQ4ytLfU2JEVOSf-8EvSJLc"; + createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MQQrCMBBG4buM25BkUgWdlSfwDj_pQIMdDTEVofTu9gBdv4-3UkWDkaybo1fJzwdMSWj5aLvrD1Zn9flt5AhfdLS9Tb1XCYHTzSdmP7C_XOUcYwynkCf03ZaRhNPgSA1lPvptf8HXaaZ6AAAA.m-m4uaNM1LhyCcQyncr7tVKcNA5dAE0SLUeNI8THq7w"; + createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ6CMBBA4buMW_ozpa3QlSfwDkM7hipFgtWYEO4uB3D9vbwNFlqpQNj2BuYcH1cqDAHeL14v_KWyTCzjs0AD9KFK62FjrUtQCk0vDaJsUbouWK21Oqk4Uj3anCCgaRvgQnn6_7vXfADq5J3rOtHffCusxV4MNGjB3jEm68_WGNh_tMDYSqcAAAA.G6ARBhqRNiSKHYtEdMW_Qh1d5lAa0CzgXEjlxN3NRLU"; + createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ7CIBBA4buM2_IzQCuw8gTeYQqTFC3aVDQmTe9uD-D6e3kbLLRShbjtHTxKul-pMkR4v3i98JfqMrNMzwod0IcarYdNrS1RKTRBGkRpUfY-Oq21Oqk0UTvakiGisR1wpTL__91aOWDMIRtGFnq0Xrg0oBh7rwUOIZPzaPV5gP0HuCPau6cAAAA.5CGFhEz1i9RLKfFMYHA7cOg3sdfFEDZnqbBHSP9R_XY"; + createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ6CMBBA4buMW_oz7VChK0_gHcZSQpUiwWpMCHe3B3D9vbwdVt44g9-PBpYUHlfOETy8X3G7xC_ndY4yPDM0wB8uvFWbSlm9Umh6aRClRdl2nrTW6qTCxKW2aQCPxjYQM6f5_-9eUgXqWzThRmKk8SzIaBSMzgnXsuuI-sFqguMH0SvcYacAAAA.qW_gqkc8RQJM-UbFVj7xldSEv1RORO4qlw6VMrTEmM0"; + createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MSw7CIBRA0b08p_yhFBi5AvfwApiiRQmiMWm6d7sAx-fmbtCwY4Ww7QQeJd4vWDMEeL9yP-cv1rZmFp8VCOAHB_bDljFa4Fwqz5SUTEs2uWCEEPzE44LjaEuCIJUmkCuW9f_vNsoBaJ1yYnZ0Rqep8VlRnESi3khrklFeXC3sP3hOgQ2nAAAA.bkPBbfpLd21eaJE2gjzniUx5n9VvCqWSY_zBiu8oO9k"; + + Map tokenByMap = JwtHelper.getTokenByMap(createTokenWithMapToken); + + // 转为Java实体对戏那个 + User user = JSONObject.parseObject(JSONObject.toJSONString(tokenByMap), User.class); + + System.out.println(user); + } + + @Test + void getTokenByMap1() { + String createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MSw6CMBRG4b1cp_R5i0BHrsA9_K01VKkSrMaEsHdZgOPv5Kw0Y0Ehv24NPXK8n1ESeXq_0nJKX5R5SjI-CzWEDyqW3cZaZ6-UsYO0xkg2su2901qrg4oj6t7mC3ljuaFUkKf_v1vNO8QIx51l0YIhXOicCGAnrr3trT4OgVOg7Qcl-35JpwAAAA.brAkeCBAcsRqKRbuvfrH-toHOhji6YcTaVPBYIxAdFo"; + createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MyQ3CMBBA0V6Ga7yMY8vLiQroYXBGiiGGyBiEFKV3UgDn9_U3WKlRhbTtAzxKvl-oMiR4v7id-Ut1XVjmZ4UB6EOd2mFz72tSCk2UBlGOKF1IVmutTirP1I-2TJDQjANwpbL8_916OcCbq7dkWeTAXlgfJhEnp4ULGckjZW0i7D9IMrwJpwAAAA.VmohGapOUVUNFQ9XVUX-QALeFQLad1f3Hp8NbcVZuMI"; + createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ7CIBBA4buMW36nQAsrT-AdpoApWrSpaEya3t0ewPX38jZYaKUKYdsZPEq8X6hmCPB-5fWcv1SXOYv4rMCAPtRoPWxqbQlSavQCtRadFnYIRiklTzJO1I62JAgaOwa5Upn__26tHIBjTOSvxB2agRurDCeTHMceE1nne6dH2H-VOEqApwAAAA.j5BcFLT-2HENeYS8LvD27tyRnI1rE-iFzjBy1iY02T4"; + createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ7CIBBA4buM2_JXWkpZeQLvMNIhRYsSRGPS9O5yANffy9shY8EEbj86eER_v2AicPB-UTnTF1PeiPtngg7wgxVLs7XW7IRQ_cx7pbhWfLRukFKKk_Ar1tbGBZzqdQeUMG7_f7caG1zlZCZDyGavFzZ4MzC0ZmIWQ1DWeBtGguMHw7854qcAAAA.V4VLIJ7vUqnfd1LeQkXa3t8V_376DWVAA_g0PE_6_S8"; + + Map tokenByMap = JwtHelper.getTokenByMap(createTokenWithMapToken, key); + // 转为Java实体对戏那个 + User user = JSONObject.parseObject(JSONObject.toJSONString(tokenByMap), User.class); + System.out.println(user); + } +} \ No newline at end of file From 4d5bab81e56b7527f16939a57c5f25ccb86130af Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Fri, 31 May 2024 15:01:39 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat(=E6=96=B0=E5=A2=9E):=20:rocket:=20?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=BE=AE=E6=9C=8D=E5=8A=A1=E4=B8=AD=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E4=BC=A0=E9=80=92=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/common-service/pom.xml | 37 +++++++++++++++++++ .../EnableUserTokenFeignInterceptor.java | 16 ++++++++ .../UserTokenFeignInterceptor.java | 21 +++++++++++ common/pom.xml | 1 + 4 files changed, 75 insertions(+) create mode 100644 common/common-service/pom.xml create mode 100644 common/common-service/src/main/java/cn/bunny/common/service/annotaion/EnableUserTokenFeignInterceptor.java create mode 100644 common/common-service/src/main/java/cn/bunny/common/service/interceptor/UserTokenFeignInterceptor.java diff --git a/common/common-service/pom.xml b/common/common-service/pom.xml new file mode 100644 index 0000000..9256325 --- /dev/null +++ b/common/common-service/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + + cn.bunny + common + 0.0.1-SNAPSHOT + + + common-service + jar + + common-service + https://maven.apache.org + + + UTF-8 + + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + org.springframework.cloud + spring-cloud-loadbalancer + + + jakarta.servlet + jakarta.servlet-api + 6.1.0-M2 + + + diff --git a/common/common-service/src/main/java/cn/bunny/common/service/annotaion/EnableUserTokenFeignInterceptor.java b/common/common-service/src/main/java/cn/bunny/common/service/annotaion/EnableUserTokenFeignInterceptor.java new file mode 100644 index 0000000..a24ba5b --- /dev/null +++ b/common/common-service/src/main/java/cn/bunny/common/service/annotaion/EnableUserTokenFeignInterceptor.java @@ -0,0 +1,16 @@ +package cn.bunny.common.service.annotaion; + +import cn.bunny.common.service.interceptor.UserTokenFeignInterceptor; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = ElementType.TYPE) +@Import(value = UserTokenFeignInterceptor.class) +public @interface EnableUserTokenFeignInterceptor { + +} \ No newline at end of file diff --git a/common/common-service/src/main/java/cn/bunny/common/service/interceptor/UserTokenFeignInterceptor.java b/common/common-service/src/main/java/cn/bunny/common/service/interceptor/UserTokenFeignInterceptor.java new file mode 100644 index 0000000..20026cb --- /dev/null +++ b/common/common-service/src/main/java/cn/bunny/common/service/interceptor/UserTokenFeignInterceptor.java @@ -0,0 +1,21 @@ +package cn.bunny.common.service.interceptor; + +import feign.RequestInterceptor; +import feign.RequestTemplate; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +/** + * 传递请求头,在微服务中 + */ +public class UserTokenFeignInterceptor implements RequestInterceptor { + @Override + public void apply(RequestTemplate requestTemplate) { + ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + assert requestAttributes != null; + HttpServletRequest request = requestAttributes.getRequest(); + String token = request.getHeader("token"); + requestTemplate.header("token", token); + } +} \ No newline at end of file diff --git a/common/pom.xml b/common/pom.xml index 19d4c57..54331e5 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -15,6 +15,7 @@ service-utils common-generator common-utils + common-service From bb23937744d66781e38c8e344190e1c85881470c Mon Sep 17 00:00:00 2001 From: Bunny <1319900154@qq.com> Date: Sat, 1 Jun 2024 16:51:13 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=20feat(=E6=96=B0=E5=A2=9E):=20:rocket:=20J?= =?UTF-8?q?WT=E9=94=99=E8=AF=AF=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= =?UTF-8?q?=EF=BC=8CAOP=E5=88=87=E9=9D=A2=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/common-utils/pom.xml | 27 ---- common/pom.xml | 1 - .../bunny/common/service}/utils/FileUtil.java | 2 +- .../bunny/common/service/utils/JwtHelper.java | 117 +++++++++++------- .../cn/bunny/entity/system/log/SystemLog.java | 75 +++++++++++ service/service-web/pom.xml | 5 - .../service/web/aop/annotation/SkipLog.java | 11 ++ .../web/aop/aspect/AutoFillAspect.java | 4 +- .../service/web/aop/aspect/AutoLogAspect.java | 97 +++++++++++++++ .../service/web/mapper/SystemLogMapper.java | 18 +++ .../main/resources/mapper/SystemLogMapper.xml | 28 +++++ 11 files changed, 305 insertions(+), 80 deletions(-) delete mode 100644 common/common-utils/pom.xml rename common/{common-utils/src/main/java/cn/bunny/common => service-utils/src/main/java/cn/bunny/common/service}/utils/FileUtil.java (95%) create mode 100644 dao/src/main/java/cn/bunny/entity/system/log/SystemLog.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/aop/annotation/SkipLog.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoLogAspect.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/mapper/SystemLogMapper.java create mode 100644 service/service-web/src/main/resources/mapper/SystemLogMapper.xml diff --git a/common/common-utils/pom.xml b/common/common-utils/pom.xml deleted file mode 100644 index 943745a..0000000 --- a/common/common-utils/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - 4.0.0 - - cn.bunny - common - 0.0.1-SNAPSHOT - - - common-utils - jar - - common-utils - https://maven.apache.org - - - UTF-8 - - - - - cn.bunny - dao - 0.0.1-SNAPSHOT - - - diff --git a/common/pom.xml b/common/pom.xml index 54331e5..2569da4 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -14,7 +14,6 @@ service-utils common-generator - common-utils common-service diff --git a/common/common-utils/src/main/java/cn/bunny/common/utils/FileUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/FileUtil.java similarity index 95% rename from common/common-utils/src/main/java/cn/bunny/common/utils/FileUtil.java rename to common/service-utils/src/main/java/cn/bunny/common/service/utils/FileUtil.java index 739253c..4d40dcc 100644 --- a/common/common-utils/src/main/java/cn/bunny/common/utils/FileUtil.java +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/FileUtil.java @@ -1,4 +1,4 @@ -package cn.bunny.common.utils; +package cn.bunny.common.service.utils; public class FileUtil { public static String getSize(Long fileSize) { diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java index 1f5e5d4..07394bf 100644 --- a/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java @@ -1,6 +1,7 @@ package cn.bunny.common.service.utils; import io.jsonwebtoken.*; +import io.micrometer.common.lang.Nullable; import org.springframework.util.StringUtils; import java.util.Date; @@ -205,12 +206,17 @@ public class JwtHelper { * @param token token * @return map集合 */ - public static Map getTokenByMap(String token) { - if (!StringUtils.hasText(token)) return null; - Claims claims = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody(); + public static Map getMapByToken(String token) { + try { + if (!StringUtils.hasText(token)) return null; + Claims claims = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody(); - // 将 body 值转为map - return new HashMap<>(claims); + // 将 body 值转为map + return new HashMap<>(claims); + + } catch (Exception exception) { + return null; + } } /** @@ -220,12 +226,17 @@ public class JwtHelper { * @param signKey 秘钥 * @return map集合 */ - public static Map getTokenByMap(String token, String signKey) { - if (!StringUtils.hasText(token)) return null; - Jws claimsJws = Jwts.parser().setSigningKey(signKey).parseClaimsJws(token); - Claims body = claimsJws.getBody(); - // 将 body 值转为map - return new HashMap<>(body); + public static Map getMapByToken(String token, String signKey) { + try { + if (!StringUtils.hasText(token)) return null; + Jws claimsJws = Jwts.parser().setSigningKey(signKey).parseClaimsJws(token); + Claims body = claimsJws.getBody(); + // 将 body 值转为map + return new HashMap<>(body); + + } catch (Exception exception) { + return null; + } } /** @@ -234,12 +245,22 @@ public class JwtHelper { * @param token token * @return 主题 */ - public static String getTokenBySubject(String token) { - if (!StringUtils.hasText(token)) return null; - Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); - Claims body = claimsJws.getBody(); + public static String getSubjectByToken(String token) { + return getSubjectByTokenHandler(token, tokenSignKey); + } - return body.getSubject(); + @Nullable + private static String getSubjectByTokenHandler(String token, String tokenSignKey) { + try { + if (!StringUtils.hasText(token)) return null; + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Claims body = claimsJws.getBody(); + + return body.getSubject(); + + } catch (Exception exception) { + return null; + } } /** @@ -248,12 +269,8 @@ public class JwtHelper { * @param token token * @return 主题 */ - public static String getTokenBySubject(String token, String tokenSignKey) { - if (!StringUtils.hasText(token)) return null; - Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); - Claims body = claimsJws.getBody(); - - return body.getSubject(); + public static String getSubjectByToken(String token, String tokenSignKey) { + return getSubjectByTokenHandler(token, tokenSignKey); } /** @@ -263,12 +280,16 @@ public class JwtHelper { * @return 用户ID */ public static Long getUserId(String token) { - if (!StringUtils.hasText(token)) return null; + try { + if (!StringUtils.hasText(token)) return null; - Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); - Claims claims = claimsJws.getBody(); + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Claims claims = claimsJws.getBody(); - return Long.valueOf(String.valueOf(claims.get("userId"))); + return Long.valueOf(String.valueOf(claims.get("userId"))); + } catch (Exception exception) { + return null; + } } /** @@ -278,11 +299,15 @@ public class JwtHelper { * @return 用户名 */ public static String getUsername(String token) { - if (!StringUtils.hasText(token)) return ""; + try { + if (!StringUtils.hasText(token)) return ""; - Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); - Claims claims = claimsJws.getBody(); - return (String) claims.get("userName"); + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Claims claims = claimsJws.getBody(); + return (String) claims.get("userName"); + } catch (Exception exception) { + return null; + } } /** @@ -292,10 +317,7 @@ public class JwtHelper { * @return 是否过期 */ public static boolean isExpired(String token) { - Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); - Date expiration = claimsJws.getBody().getExpiration(); - - return expiration != null && expiration.before(new Date()); + return isExpiredUtil(token, tokenSignKey); } /** @@ -305,17 +327,24 @@ public class JwtHelper { * @return 是否过期 */ public static boolean isExpired(String token, String tokenSignKey) { - Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); - Date expiration = claimsJws.getBody().getExpiration(); - - return expiration != null && expiration.before(new Date()); + return isExpiredUtil(token, tokenSignKey); } - public static void main(String[] args) { - String token = JwtHelper.createToken(7L, "admin", 7); - System.out.println(token); - // token = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_6tWKi5NUrJScirNy6vUDQ12DVLSUUqtKFCyMjQ3MTc0NrYwNddRKi1OLfJMUbKyNDIwNLQwMDAzg4j5JeamAjUbGhtaWhoYGJqaOBQW6iXn5yrVAgCrO9jLWAAAAA.DS1wYprXGoIMrjtUWfDSN9AG5gWoRZ17oAgcvC0kwag"; - // System.out.println(JwtHelper.getUserId(token)); - // System.out.println(JwtHelper.getUsername(token)); + /** + * 判断是否过期 + * + * @param token token + * @param tokenSignKey key值 + * @return 是否过期 + */ + private static boolean isExpiredUtil(String token, String tokenSignKey) { + try { + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Date expiration = claimsJws.getBody().getExpiration(); + + return expiration != null && expiration.before(new Date()); + } catch (Exception exception) { + return true; + } } } \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/entity/system/log/SystemLog.java b/dao/src/main/java/cn/bunny/entity/system/log/SystemLog.java new file mode 100644 index 0000000..18781db --- /dev/null +++ b/dao/src/main/java/cn/bunny/entity/system/log/SystemLog.java @@ -0,0 +1,75 @@ +package cn.bunny.entity.system.log; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 系统日志表 + *

+ * + * @author Bunny + * @since 2024-05-31 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("system_log") +@ApiModel(value = "SystemLog对象", description = "系统日志表") +public class SystemLog implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty("所在类路径") + private String classPath; + + @ApiModelProperty("执行方法名称") + private String methodName; + + @ApiModelProperty("入参内容") + private String args; + + @ApiModelProperty("返回参数") + private String result; + + @ApiModelProperty("报错堆栈") + private String errorStack; + + @ApiModelProperty("报错") + private String errorMessage; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("用户名") + private String nickname; + + @ApiModelProperty("当前用户token") + private String token; + + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + @ApiModelProperty("更新时间") + private LocalDateTime updateTime; + + @ApiModelProperty("更新用户") + private Long updateUser; + + @ApiModelProperty("是否被删除") + private Boolean isDeleted; +} diff --git a/service/service-web/pom.xml b/service/service-web/pom.xml index 7459383..f7eb809 100644 --- a/service/service-web/pom.xml +++ b/service/service-web/pom.xml @@ -26,11 +26,6 @@ module-mail 0.0.1-SNAPSHOT
- - cn.bunny - common-utils - 0.0.1-SNAPSHOT - cn.bunny module-minio diff --git a/service/service-web/src/main/java/cn/bunny/service/web/aop/annotation/SkipLog.java b/service/service-web/src/main/java/cn/bunny/service/web/aop/annotation/SkipLog.java new file mode 100644 index 0000000..87ae32c --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/aop/annotation/SkipLog.java @@ -0,0 +1,11 @@ +package cn.bunny.service.web.aop.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface SkipLog { +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoFillAspect.java b/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoFillAspect.java index 7d2fc45..2c29962 100644 --- a/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoFillAspect.java +++ b/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoFillAspect.java @@ -1,4 +1,4 @@ -package cn.bunny.service.aop.aspect; +package cn.bunny.service.web.aop.aspect; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; @@ -11,7 +11,7 @@ import org.springframework.stereotype.Component; @Component @Slf4j public class AutoFillAspect { - @Pointcut("execution(* cn.bunny.service.*.*(..))") + @Pointcut("execution(* cn.bunny.service.web.service.impl..*(..))") public void autoFillPointcut() { } diff --git a/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoLogAspect.java b/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoLogAspect.java new file mode 100644 index 0000000..6ad8d09 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoLogAspect.java @@ -0,0 +1,97 @@ +package cn.bunny.service.web.aop.aspect; + +import cn.bunny.common.service.utils.JwtHelper; +import cn.bunny.entity.system.log.SystemLog; +import cn.bunny.service.web.aop.annotation.SkipLog; +import cn.bunny.service.web.mapper.SystemLogMapper; +import cn.bunny.vo.system.login.LoginVo; +import com.alibaba.fastjson2.JSONObject; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.Arrays; +import java.util.Map; + +@Aspect +@Component +@Slf4j +public class AutoLogAspect { + @Autowired + private SystemLogMapper systemLogMapper; + + @Pointcut("execution(* cn.bunny.service.web.controller..*(..))") + public void point() { + } + + @Around(value = "point()") + public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable { + Object result; + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + // 是否有跳过注解,如果有跳过注解就不执行当前操作!!! + SkipLog annotation = signature.getMethod().getAnnotation(SkipLog.class); + // 目标方法所在类名路径 + String classPath = joinPoint.getSignature().getDeclaringTypeName(); + // 当前执行的方法名 + String methodName = signature.getName(); + // 入参内容 + String args = Arrays.toString(joinPoint.getArgs()); + // 获取用户token + ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = requestAttributes.getRequest(); + String token = request.getHeader("token"); + // 初始化系统日志对象 + SystemLog systemLog = new SystemLog(); + // token转为实体对象 + Map mapByToken = JwtHelper.getMapByToken(token); + LoginVo loginVo = JSONObject.parseObject(JSONObject.toJSONString(mapByToken), LoginVo.class); + + + try { + // 当为null时跳过执行 + if (annotation != null) return joinPoint.proceed(); + + // TODO 将请求头token全部转成 map + systemLog.setClassPath(classPath); + systemLog.setMethodName(methodName); + if (args.equals("[null]")) { + systemLog.setArgs(null); + } else { + systemLog.setArgs(args); + } + systemLog.setToken(token); + + systemLog.setNickname(loginVo.getNickName()); + systemLog.setEmail(loginVo.getEmail()); + systemLog.setUpdateUser(loginVo.getId()); + + // 目标对象(连接点)方法的执行 + result = joinPoint.proceed(); + systemLog.setResult(JSONObject.toJSONString(result)); + } catch (Exception exception) { + String message = exception.getMessage(); + StackTraceElement[] stackTrace = exception.getStackTrace(); + + // 如果报错,设置报错的堆栈和消息,放到数据库中 + systemLog.setErrorStack(Arrays.toString(stackTrace)); + systemLog.setErrorMessage(message); + + // 插入日志数据到数据库 + systemLogMapper.insert(systemLog); + + throw exception; + } + + // 插入日志数据到数据库 + systemLogMapper.insert(systemLog); + return result; + } +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/mapper/SystemLogMapper.java b/service/service-web/src/main/java/cn/bunny/service/web/mapper/SystemLogMapper.java new file mode 100644 index 0000000..9392aad --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/mapper/SystemLogMapper.java @@ -0,0 +1,18 @@ +package cn.bunny.service.web.mapper; + +import cn.bunny.entity.system.log.SystemLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 系统日志表 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-05-31 + */ +@Mapper +public interface SystemLogMapper extends BaseMapper { + +} diff --git a/service/service-web/src/main/resources/mapper/SystemLogMapper.xml b/service/service-web/src/main/resources/mapper/SystemLogMapper.xml new file mode 100644 index 0000000..8ff2465 --- /dev/null +++ b/service/service-web/src/main/resources/mapper/SystemLogMapper.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + id, class_path, method_name, args, result, error_stack, error_message, email, nickname, token, create_time, update_time, update_user, is_deleted + + +