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