From ae1b8d46541101e1fcda6404c0a79e33f4b18df4 Mon Sep 17 00:00:00 2001 From: EightMonth Date: Wed, 19 Jun 2024 11:15:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=95=B0=E6=8D=AE=E8=84=B1?= =?UTF-8?q?=E6=95=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SensitiveFieldSerialize.java | 87 +++++++++++++++++++ .../annotation/SensitiveDecode.java | 2 + .../annotation/SensitiveEncode.java | 2 + .../annotation/SensitiveField.java | 5 ++ .../util/SensitiveInfoUtil.java | 24 ++--- 5 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/SensitiveFieldSerialize.java diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/SensitiveFieldSerialize.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/SensitiveFieldSerialize.java new file mode 100644 index 00000000..d65de555 --- /dev/null +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/SensitiveFieldSerialize.java @@ -0,0 +1,87 @@ +package org.jeecg.common.desensitization; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.ContextualSerializer; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.desensitization.annotation.SensitiveField; +import org.jeecg.common.desensitization.enums.SensitiveEnum; +import org.jeecg.common.desensitization.util.SensitiveInfoUtil; +import org.jeecg.common.util.encryption.AesEncryptUtil; + +import java.io.IOException; +import java.util.Objects; + +/** + * @author eightmonth@qq.com + * @date 2024/6/19 10:43 + */ +@NoArgsConstructor +@AllArgsConstructor +@Slf4j +public class SensitiveFieldSerialize extends JsonSerializer implements ContextualSerializer { + + private SensitiveEnum type; + + @Override + public void serialize(String data, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + switch (type){ + case ENCODE: + try { + jsonGenerator.writeString(AesEncryptUtil.encrypt(data)); + } catch (Exception exception) { + log.error("数据加密错误", exception.getMessage()); + jsonGenerator.writeString(data); + } + break; + case CHINESE_NAME: + jsonGenerator.writeString(SensitiveInfoUtil.chineseName(data)); + break; + case ID_CARD: + jsonGenerator.writeString(SensitiveInfoUtil.idCardNum(data)); + break; + case FIXED_PHONE: + jsonGenerator.writeString(SensitiveInfoUtil.fixedPhone(data)); + break; + case MOBILE_PHONE: + jsonGenerator.writeString(SensitiveInfoUtil.mobilePhone(data)); + break; + case ADDRESS: + jsonGenerator.writeString(SensitiveInfoUtil.address(data, 3)); + break; + case EMAIL: + jsonGenerator.writeString(SensitiveInfoUtil.email(data)); + break; + case BANK_CARD: + jsonGenerator.writeString(SensitiveInfoUtil.bankCard(data)); + break; + case CNAPS_CODE: + jsonGenerator.writeString(SensitiveInfoUtil.cnapsCode(data)); + break; + default: + jsonGenerator.writeString(data); + } + } + + @Override + public JsonSerializer createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException { + if (beanProperty != null) { + if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) { + SensitiveField sensitive = beanProperty.getAnnotation(SensitiveField.class); + if (sensitive == null) { + sensitive = beanProperty.getContextAnnotation(SensitiveField.class); + } + if (sensitive != null) { + return new SensitiveFieldSerialize(sensitive.type()); + } + } + return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty); + } + return serializerProvider.findNullValueSerializer(null); + } +} diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveDecode.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveDecode.java index 698ecba3..6583fb41 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveDecode.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveDecode.java @@ -6,10 +6,12 @@ import java.lang.annotation.*; * 解密注解 * * 在方法上定义 将方法返回对象中的敏感字段 解密,需要注意的是,如果没有加密过,解密会出问题,返回原字符串 + * @deprecated 直接在实体的字段中使用@{@link SensitiveField}即可 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) +@Deprecated public @interface SensitiveDecode { /** diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveEncode.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveEncode.java index eb89d75e..b3a98afc 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveEncode.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveEncode.java @@ -6,10 +6,12 @@ import java.lang.annotation.*; * 加密注解 * * 在方法上声明 将方法返回对象中的敏感字段 加密/格式化 + * @deprecated 直接在实体的字段中使用@{@link SensitiveField}即可 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) +@Deprecated public @interface SensitiveEncode { /** diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveField.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveField.java index a887e5a5..72d1f5e9 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveField.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/annotation/SensitiveField.java @@ -1,6 +1,9 @@ package org.jeecg.common.desensitization.annotation; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.jeecg.common.desensitization.SensitiveFieldSerialize; import org.jeecg.common.desensitization.enums.SensitiveEnum; import java.lang.annotation.*; @@ -11,6 +14,8 @@ import java.lang.annotation.*; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) +@JacksonAnnotationsInside +@JsonSerialize(using = SensitiveFieldSerialize.class) public @interface SensitiveField { /** diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/util/SensitiveInfoUtil.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/util/SensitiveInfoUtil.java index b6b1a6af..820047e0 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/util/SensitiveInfoUtil.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/desensitization/util/SensitiveInfoUtil.java @@ -198,7 +198,7 @@ public class SensitiveInfoUtil { * @param fullName 全名 * @return <例子:李**> */ - private static String chineseName(String fullName) { + public static String chineseName(String fullName) { if (oConvertUtils.isEmpty(fullName)) { return ""; } @@ -211,7 +211,7 @@ public class SensitiveInfoUtil { * @param firstName 名 * @return <例子:李**> */ - private static String chineseName(String familyName, String firstName) { + public static String chineseName(String familyName, String firstName) { if (oConvertUtils.isEmpty(familyName) || oConvertUtils.isEmpty(firstName)) { return ""; } @@ -223,7 +223,7 @@ public class SensitiveInfoUtil { * @param id 身份证号 * @return <例子:*************5762> */ - private static String idCardNum(String id) { + public static String idCardNum(String id) { if (oConvertUtils.isEmpty(id)) { return ""; } @@ -236,7 +236,7 @@ public class SensitiveInfoUtil { * @param num 固定电话 * @return <例子:****1234> */ - private static String fixedPhone(String num) { + public static String fixedPhone(String num) { if (oConvertUtils.isEmpty(num)) { return ""; } @@ -248,7 +248,7 @@ public class SensitiveInfoUtil { * @param num 手机号码 * @return <例子:138******1234> */ - private static String mobilePhone(String num) { + public static String mobilePhone(String num) { if (oConvertUtils.isEmpty(num)) { return ""; } @@ -265,7 +265,7 @@ public class SensitiveInfoUtil { * @param sensitiveSize 敏感信息长度 * @return <例子:北京市海淀区****> */ - private static String address(String address, int sensitiveSize) { + public static String address(String address, int sensitiveSize) { if (oConvertUtils.isEmpty(address)) { return ""; } @@ -281,7 +281,7 @@ public class SensitiveInfoUtil { * @param email 电子邮箱 * @return <例子:g**@163.com> */ - private static String email(String email) { + public static String email(String email) { if (oConvertUtils.isEmpty(email)) { return ""; } @@ -300,7 +300,7 @@ public class SensitiveInfoUtil { * @param cardNum 银行卡号 * @return <例子:6222600**********1234> */ - private static String bankCard(String cardNum) { + public static String bankCard(String cardNum) { if (oConvertUtils.isEmpty(cardNum)) { return ""; } @@ -312,7 +312,7 @@ public class SensitiveInfoUtil { * @param code 公司开户银行联号 * @return <例子:12********> */ - private static String cnapsCode(String code) { + public static String cnapsCode(String code) { if (oConvertUtils.isEmpty(code)) { return ""; } @@ -326,7 +326,7 @@ public class SensitiveInfoUtil { * @param reservedLength 保留长度 * @return 格式化后的字符串 */ - private static String formatRight(String str, int reservedLength){ + public static String formatRight(String str, int reservedLength){ String name = str.substring(0, reservedLength); String stars = String.join("", Collections.nCopies(str.length()-reservedLength, "*")); return name + stars; @@ -338,7 +338,7 @@ public class SensitiveInfoUtil { * @param reservedLength 保留长度 * @return 格式化后的字符串 */ - private static String formatLeft(String str, int reservedLength){ + public static String formatLeft(String str, int reservedLength){ int len = str.length(); String show = str.substring(len-reservedLength); String stars = String.join("", Collections.nCopies(len-reservedLength, "*")); @@ -352,7 +352,7 @@ public class SensitiveInfoUtil { * @param endLen 结尾保留长度 * @return 格式化后的字符串 */ - private static String formatBetween(String str, int beginLen, int endLen){ + public static String formatBetween(String str, int beginLen, int endLen){ int len = str.length(); String begin = str.substring(0, beginLen); String end = str.substring(len-endLen);