From d9062f8b060a6f70108d1e0763b3981a05469666 Mon Sep 17 00:00:00 2001 From: RuoYi <yzz_ivy@163.com> Date: 星期一, 08 四月 2024 13:15:42 +0800 Subject: [PATCH] 新增数据脱敏过滤注解 --- src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java | 49 +++++++++ src/main/java/com/ruoyi/framework/aspectj/lang/enums/DesensitizedType.java | 59 +++++++++++ src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Sensitive.java | 24 ++++ src/main/java/com/ruoyi/common/utils/StringUtils.java | 46 +++++++++ src/main/java/com/ruoyi/framework/config/SensitiveJsonSerializer.java | 67 +++++++++++++ 5 files changed, 245 insertions(+), 0 deletions(-) diff --git a/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java b/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java new file mode 100644 index 0000000..f8a4c02 --- /dev/null +++ b/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java @@ -0,0 +1,49 @@ +package com.ruoyi.common.utils; + +/** + * 鑴辨晱宸ュ叿绫� + * + * @author ruoyi + */ +public class DesensitizedUtil +{ + /** + * 瀵嗙爜鐨勫叏閮ㄥ瓧绗﹂兘鐢�*浠f浛锛屾瘮濡傦細****** + * + * @param password 瀵嗙爜 + * @return 鑴辨晱鍚庣殑瀵嗙爜 + */ + public static String password(String password) + { + if (StringUtils.isBlank(password)) + { + return StringUtils.EMPTY; + } + return StringUtils.repeat('*', password.length()); + } + + /** + * 杞︾墝涓棿鐢�*浠f浛锛屽鏋滄槸閿欒鐨勮溅鐗岋紝涓嶅鐞� + * + * @param carLicense 瀹屾暣鐨勮溅鐗屽彿 + * @return 鑴辨晱鍚庣殑杞︾墝 + */ + public static String carLicense(String carLicense) + { + if (StringUtils.isBlank(carLicense)) + { + return StringUtils.EMPTY; + } + // 鏅�氳溅鐗� + if (carLicense.length() == 7) + { + carLicense = StringUtils.hide(carLicense, 3, 6); + } + else if (carLicense.length() == 8) + { + // 鏂拌兘婧愯溅鐗� + carLicense = StringUtils.hide(carLicense, 3, 7); + } + return carLicense; + } +} diff --git a/src/main/java/com/ruoyi/common/utils/StringUtils.java b/src/main/java/com/ruoyi/common/utils/StringUtils.java index 215d115..fc6c6b5 100644 --- a/src/main/java/com/ruoyi/common/utils/StringUtils.java +++ b/src/main/java/com/ruoyi/common/utils/StringUtils.java @@ -23,6 +23,9 @@ /** 涓嬪垝绾� */ private static final char SEPARATOR = '_'; + /** 鏄熷彿 */ + private static final char ASTERISK = '*'; + /** * 鑾峰彇鍙傛暟涓嶄负绌哄�� * @@ -164,6 +167,49 @@ } /** + * 鏇挎崲鎸囧畾瀛楃涓茬殑鎸囧畾鍖洪棿鍐呭瓧绗︿负"*" + * + * @param str 瀛楃涓� + * @param startInclude 寮�濮嬩綅缃紙鍖呭惈锛� + * @param endExclude 缁撴潫浣嶇疆锛堜笉鍖呭惈锛� + * @return 鏇挎崲鍚庣殑瀛楃涓� + */ + public static String hide(CharSequence str, int startInclude, int endExclude) + { + if (isEmpty(str)) + { + return NULLSTR; + } + final int strLength = str.length(); + if (startInclude > strLength) + { + return NULLSTR; + } + if (endExclude > strLength) + { + endExclude = strLength; + } + if (startInclude > endExclude) + { + // 濡傛灉璧峰浣嶇疆澶т簬缁撴潫浣嶇疆锛屼笉鏇挎崲 + return NULLSTR; + } + final char[] chars = new char[strLength]; + for (int i = 0; i < strLength; i++) + { + if (i >= startInclude && i < endExclude) + { + chars[i] = ASTERISK; + } + else + { + chars[i] = str.charAt(i); + } + } + return new String(chars); + } + + /** * 鎴彇瀛楃涓� * * @param str 瀛楃涓� diff --git a/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Sensitive.java b/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Sensitive.java new file mode 100644 index 0000000..ae121fa --- /dev/null +++ b/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Sensitive.java @@ -0,0 +1,24 @@ +package com.ruoyi.framework.aspectj.lang.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.ruoyi.framework.aspectj.lang.enums.DesensitizedType; +import com.ruoyi.framework.config.SensitiveJsonSerializer; + +/** + * 鏁版嵁鑴辨晱娉ㄨВ + * + * @author ruoyi + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@JacksonAnnotationsInside +@JsonSerialize(using = SensitiveJsonSerializer.class) +public @interface Sensitive +{ + DesensitizedType desensitizedType(); +} diff --git a/src/main/java/com/ruoyi/framework/aspectj/lang/enums/DesensitizedType.java b/src/main/java/com/ruoyi/framework/aspectj/lang/enums/DesensitizedType.java new file mode 100644 index 0000000..619f5a5 --- /dev/null +++ b/src/main/java/com/ruoyi/framework/aspectj/lang/enums/DesensitizedType.java @@ -0,0 +1,59 @@ +package com.ruoyi.framework.aspectj.lang.enums; + +import java.util.function.Function; +import com.ruoyi.common.utils.DesensitizedUtil; + +/** + * 鑴辨晱绫诲瀷 + * + * @author ruoyi + */ +public enum DesensitizedType +{ + /** + * 濮撳悕锛岀2浣嶆槦鍙锋浛鎹� + */ + USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")), + + /** + * 瀵嗙爜锛屽叏閮ㄥ瓧绗﹂兘鐢�*浠f浛 + */ + PASSWORD(DesensitizedUtil::password), + + /** + * 韬唤璇侊紝涓棿10浣嶆槦鍙锋浛鎹� + */ + ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")), + + /** + * 鎵嬫満鍙凤紝涓棿4浣嶆槦鍙锋浛鎹� + */ + PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")), + + /** + * 鐢靛瓙閭锛屼粎鏄剧ず绗竴涓瓧姣嶅拰@鍚庨潰鐨勫湴鍧�鏄剧ず锛屽叾浠栨槦鍙锋浛鎹� + */ + EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")), + + /** + * 閾惰鍗″彿锛屼繚鐣欐渶鍚�4浣嶏紝鍏朵粬鏄熷彿鏇挎崲 + */ + BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")), + + /** + * 杞︾墝鍙风爜锛屽寘鍚櫘閫氳溅杈嗐�佹柊鑳芥簮杞﹁締 + */ + CAR_LICENSE(DesensitizedUtil::carLicense); + + private final Function<String, String> desensitizer; + + DesensitizedType(Function<String, String> desensitizer) + { + this.desensitizer = desensitizer; + } + + public Function<String, String> desensitizer() + { + return desensitizer; + } +} diff --git a/src/main/java/com/ruoyi/framework/config/SensitiveJsonSerializer.java b/src/main/java/com/ruoyi/framework/config/SensitiveJsonSerializer.java new file mode 100644 index 0000000..a0ada33 --- /dev/null +++ b/src/main/java/com/ruoyi/framework/config/SensitiveJsonSerializer.java @@ -0,0 +1,67 @@ +package com.ruoyi.framework.config; + +import java.io.IOException; +import java.util.Objects; +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 com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.framework.aspectj.lang.annotation.Sensitive; +import com.ruoyi.framework.aspectj.lang.enums.DesensitizedType; +import com.ruoyi.framework.security.LoginUser; + +/** + * 鏁版嵁鑴辨晱搴忓垪鍖栬繃婊� + * + * @author ruoyi + */ +public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer +{ + private DesensitizedType desensitizedType; + + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException + { + if (desensitization()) + { + gen.writeString(desensitizedType.desensitizer().apply(value)); + } + else + { + gen.writeString(value); + } + } + + @Override + public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) + throws JsonMappingException + { + Sensitive annotation = property.getAnnotation(Sensitive.class); + if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) + { + this.desensitizedType = annotation.desensitizedType(); + return this; + } + return prov.findValueSerializer(property.getType(), property); + } + + /** + * 鏄惁闇�瑕佽劚鏁忓鐞� + */ + private boolean desensitization() + { + try + { + LoginUser securityUser = SecurityUtils.getLoginUser(); + // 绠$悊鍛樹笉鑴辨晱 + return !securityUser.getUser().isAdmin(); + } + catch (Exception e) + { + return true; + } + } +} -- Gitblit v1.9.3