CeDo
2021-04-01 b3c9ffbd70837a179936de9f51289516184e31a0
add: 实有人口电话以及身份证数据库加密,查询脱敏
13个文件已添加
4个文件已修改
688 ■■■■■ 已修改文件
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/dtos/community/ComMngPopulationDTO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/AESUtil.java 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/DoEncrytDecrypt.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/EncryptDecryptClass.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/EncryptDecryptField.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/EncryptQuery.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/EncryptQueryClass.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/IEncryptDecrypt.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/sensitive/Desensitizer.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/sensitive/Sensitive.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/sensitive/SensitiveStrategy.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/vos/community/ComMngPopulationVO.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/model/dos/ComMngPopulationDO.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/model/helper/encrypt/ParammeterInterceptor.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/model/helper/encrypt/ResultInterceptor.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/model/helper/sensitive/SensitiveInterceptor.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/resources/bootstrap.yml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/dtos/community/ComMngPopulationDTO.java
@@ -1,5 +1,7 @@
package com.panzhihua.common.model.dtos.community;
import com.panzhihua.common.model.helper.encrypt.EncryptQuery;
import com.panzhihua.common.model.helper.encrypt.EncryptQueryClass;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@@ -9,6 +11,7 @@
 *  实有人口DTO
 */
@Data
@EncryptQueryClass
public class ComMngPopulationDTO implements Serializable {
    private static final long serialVersionUID = 1L;
@@ -91,6 +94,7 @@
     * 身份证号码
     */
    @ApiModelProperty(value="身份证号码")
    @EncryptQuery
    private String cardNo;
    /**
     * 街路巷
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/AESUtil.java
New file
@@ -0,0 +1,178 @@
package com.panzhihua.common.model.helper;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.Base64;
/**
 * AES 工具类
 */
public class AESUtil {
    /**
     * AES 256 加密
     * @param strToEncrypt 要加密的字符串
     * @param secKey 秘钥
     * @param salt 盐
     * @return 加密后的字符串
     */
    public static String encrypt256(String strToEncrypt, String secKey, String salt) {
        try {
            byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            IvParameterSpec ivspec = new IvParameterSpec(iv);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            KeySpec spec = new PBEKeySpec(secKey.toCharArray(), salt.getBytes(), 65536, 256);
            SecretKey tmp = factory.generateSecret(spec);
            SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
            return Base64.getEncoder()
                    .encodeToString(cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_8)));
        } catch (Exception e) {
            System.out.println("Error while encrypting: " + e.toString());
        }
        return null;
    }
    /**
     * AES 256 解密
     * @param strToDecrypt 要解密的字符串
     * @param secKey 秘钥
     * @param salt 盐
     * @return 解密后的字符串
     */
    public static String decrypt256( String strToDecrypt, String secKey, String salt) {
        try {
            byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            IvParameterSpec ivspec = new IvParameterSpec(iv);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            KeySpec spec = new PBEKeySpec(secKey.toCharArray(), salt.getBytes(), 65536, 256);
            SecretKey tmp = factory.generateSecret(spec);
            SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);
            return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
        } catch (Exception e) {
            System.out.println("Error while decrypting: " + e.toString());
        }
        return null;
    }
    private static SecretKeySpec secretKey;
    private static byte[] key;
    public static void setKey(String myKey)
    {
        MessageDigest sha = null;
        try {
            key = myKey.getBytes("UTF-8");
            sha = MessageDigest.getInstance("SHA-1");
            key = sha.digest(key);
            key = Arrays.copyOf(key, 16);
            secretKey = new SecretKeySpec(key, "AES");
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
    /**
     * AES 128 加密
     * @param strToEncrypt 要加密的字符串
     * @param secret 秘钥
     * @return 加密后的字符串
     */
    public static String encrypt128(String strToEncrypt, String secret)
    {
        try
        {
            setKey(secret);
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
        }
        catch (Exception e)
        {
            System.out.println("Error while encrypting: " + e.toString());
        }
        return null;
    }
    /**
     * AES 128 解密
     * @param strToDecrypt 要解密的字符串
     * @param secret 秘钥
     * @return 解密后的字符串
     */
    public static String decrypt128(String strToDecrypt, String secret)
    {
        try
        {
            setKey(secret);
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
        }
        catch (Exception e)
        {
            System.out.println("Error while decrypting: " + e.toString());
        }
        return null;
    }
}
class AES256Example {
    public static void main(String[] args) {
        String originalString = "howtodoinjava.com";
        String secKey = "this is my super secrt key";
        String salt = "salt for me!!!";
        String encryptedString = AESUtil.encrypt256(originalString, secKey, salt);
        String decryptedString = AESUtil.decrypt256(encryptedString, secKey, salt);
        System.out.println(originalString);
        System.out.println(encryptedString);
        System.out.println(decryptedString);
    }
}
class AES128Example {
    public static void main(String[] args) {
        String[] originalString = new String[]{"51011234567892013", "13612345678", "四川省成都市高新区", "四川省成都市高新"};
        String key = "5165465461dsfas";
        Arrays.stream(originalString).forEach(os ->{
            String encryptedString = AESUtil.encrypt128(os, key);
            String decryptedString = AESUtil.decrypt128(encryptedString, key);
            System.out.println(os);
            System.out.println(encryptedString);
            System.out.println(decryptedString);
        });
    }
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/DoEncrytDecrypt.java
New file
@@ -0,0 +1,68 @@
package com.panzhihua.common.model.helper.encrypt;
import com.panzhihua.common.model.helper.AESUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/***
 * 默认实现: AES 128 加密、解密
 * 可自定义实现{@link IEncryptDecrypt }接口
 *
 * @author cedoo
 * @since 2021-4-1 10:40:52
 */
@Slf4j
@Component
public class DoEncrytDecrypt implements IEncryptDecrypt{
    @Value("${domain.aesKey:}")
    private String aesKey;
    @Override
    public <T> T encrypt(Field[] declaredFields, T parameterObject) throws IllegalAccessException {
        for (Field field : declaredFields) {
            if (field.getType() == String.class) {
                field.setAccessible(true);
                for (Annotation annotation : field.getAnnotations()) {
                    if (annotation.annotationType() == EncryptDecryptField.class || annotation.annotationType() == EncryptQuery.class) {
                        log.debug("加密字段:" + field.getName());
                        Object fieldVal = field.get(parameterObject);
                        if(fieldVal!=null) {
                            String encryptedStr = AESUtil.encrypt128(fieldVal.toString(), aesKey);
                            field.set(parameterObject, encryptedStr);
                        }
                    }
                }
            }
        }
        return parameterObject;
    }
    @Override
    public <T> T decrypt(T result) throws IllegalAccessException {
        for (Field field : result.getClass().getDeclaredFields()) {
            try {
                field.setAccessible(true);
                if (field.get(result) != null) {
                    for (Annotation annotation : field.getAnnotations()) {
                        if (annotation.annotationType() == EncryptDecryptField.class) {
                            log.debug("解密密字段:" + field.getName());
                            String fieldVal = field.get(result).toString();
                            String decryptVal = AESUtil.decrypt128(fieldVal, aesKey);
                            field.set(result, decryptVal!=null?decryptVal:fieldVal);
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                throw e;
            }
        }
        return result;
    }
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/EncryptDecryptClass.java
New file
@@ -0,0 +1,14 @@
package com.panzhihua.common.model.helper.encrypt;
import java.lang.annotation.*;
/**
 * 需要加解密的类注解
 */
@Documented
@Inherited
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptDecryptClass {
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/EncryptDecryptField.java
New file
@@ -0,0 +1,15 @@
package com.panzhihua.common.model.helper.encrypt;
import java.lang.annotation.*;
/**
 * 加密字段注解
 */
@Documented
@Inherited
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptDecryptField {
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/EncryptQuery.java
New file
@@ -0,0 +1,15 @@
package com.panzhihua.common.model.helper.encrypt;
import java.lang.annotation.*;
/**
 * 加密字段搜索
 */
@Documented
@Inherited
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptQuery {
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/EncryptQueryClass.java
New file
@@ -0,0 +1,15 @@
package com.panzhihua.common.model.helper.encrypt;
import java.lang.annotation.*;
/**
 * 加密字段搜索
 */
@Documented
@Inherited
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptQueryClass {
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/encrypt/IEncryptDecrypt.java
New file
@@ -0,0 +1,25 @@
package com.panzhihua.common.model.helper.encrypt;
import java.lang.reflect.Field;
public interface IEncryptDecrypt {
    /**
     * 加密方法
     * @param declaredFields 反射bean成员变量
     * @param parameterObject Mybatis入参
     * @param <T>
     * @return
     */
    public <T> T encrypt(Field[] declaredFields, T parameterObject) throws IllegalAccessException;
    /**
     * 解密方法
     * @param result Mybatis 返回值,需要判断是否是ArrayList类型
     * @param <T>
     * @return
     */
    public <T> T decrypt(T result) throws IllegalAccessException;
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/sensitive/Desensitizer.java
New file
@@ -0,0 +1,8 @@
package com.panzhihua.common.model.helper.sensitive;
import java.util.function.Function;
public interface Desensitizer extends Function<String,String> {
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/sensitive/Sensitive.java
New file
@@ -0,0 +1,12 @@
package com.panzhihua.common.model.helper.sensitive;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sensitive {
    SensitiveStrategy strategy();
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/helper/sensitive/SensitiveStrategy.java
New file
@@ -0,0 +1,51 @@
package com.panzhihua.common.model.helper.sensitive;
/**
 * 脱敏策略.
 *
 * @author cedoo
 * @since 2021-4-1 10:40:52
 */
public enum SensitiveStrategy {
    /**
     * Username sensitive strategy.
     */
    USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
    /**
     * Id card sensitive type.
     */
    ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1****$2")),
    /**
     * Phone sensitive type.
     */
    PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
    /**
     * Address sensitive type.
     */
    ADDRESS(s -> s.replaceAll("(\\S{8})\\S{4}(\\S*)\\S{4}", "$1****$2****")),
    /**
     * 中文地址
     */
    ADDRESS_CN(s -> {
        //List<Word> words = WordSegmenter.seg(s);
        //Arrays.toString(words.toArray());
        return s.replaceAll("(\\S{8})(\\S*)\\S{4}", "$1****$2****");
    });
    private final Desensitizer desensitizer;
    SensitiveStrategy(Desensitizer desensitizer) {
        this.desensitizer = desensitizer;
    }
    /**
     * Gets desensitizer.
     *
     * @return the desensitizer
     */
    public Desensitizer getDesensitizer() {
        return desensitizer;
    }
}
springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/vos/community/ComMngPopulationVO.java
@@ -1,5 +1,9 @@
package com.panzhihua.common.model.vos.community;
import com.panzhihua.common.model.helper.encrypt.EncryptDecryptClass;
import com.panzhihua.common.model.helper.encrypt.EncryptDecryptField;
import com.panzhihua.common.model.helper.sensitive.Sensitive;
import com.panzhihua.common.model.helper.sensitive.SensitiveStrategy;
import com.panzhihua.common.model.vos.user.ComMngFamilyInfoVO;
import com.panzhihua.common.validated.AddGroup;
import io.swagger.annotations.ApiModel;
@@ -15,6 +19,7 @@
 */
@Data
@ApiModel("实有人口表")
@EncryptDecryptClass
public class ComMngPopulationVO {
    /**
@@ -60,6 +65,8 @@
     */
    @ApiModelProperty("身份证号码")
    @NotBlank(groups = {AddGroup.class},message = "身份证号码不可为空")
    @EncryptDecryptField
    @Sensitive(strategy = SensitiveStrategy.ID_CARD)
    private String cardNo;
    /**
     * 街路巷
@@ -111,6 +118,8 @@
     */
    @ApiModelProperty("联系方式")
    @NotBlank(groups = {AddGroup.class},message = "联系方式不可为空")
    @EncryptDecryptField
    @Sensitive(strategy = SensitiveStrategy.PHONE)
    private String phone;
    /**
     * 备注
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/model/dos/ComMngPopulationDO.java
@@ -4,6 +4,8 @@
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.panzhihua.common.model.helper.encrypt.EncryptDecryptClass;
import com.panzhihua.common.model.helper.encrypt.EncryptDecryptField;
import lombok.Data;
import java.io.Serializable;
@@ -11,6 +13,7 @@
@Data
@TableName(value = "com_mng_population")
@EncryptDecryptClass
public class ComMngPopulationDO implements Serializable {
    private static final long serialVersionUID = 1L;
@@ -46,6 +49,7 @@
    /**
     * 身份证号码
     */
    @EncryptDecryptField
    private String cardNo;
    /**
     * 街路巷
@@ -82,6 +86,7 @@
    /**
     * 联系方式
     */
    @EncryptDecryptField
    private String phone;
    /**
     * 备注
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/model/helper/encrypt/ParammeterInterceptor.java
New file
@@ -0,0 +1,115 @@
package com.panzhihua.service_community.model.helper.encrypt;
import com.panzhihua.common.model.helper.encrypt.EncryptDecryptClass;
import com.panzhihua.common.model.helper.encrypt.EncryptQuery;
import com.panzhihua.common.model.helper.encrypt.EncryptQueryClass;
import com.panzhihua.common.model.helper.encrypt.IEncryptDecrypt;
import com.panzhihua.common.model.helper.sensitive.Sensitive;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.BindingException;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.util.*;
import java.util.stream.Stream;
/**
 * 加密拦截器
 * 包含加密字段查询时 的加密步骤
 * @author cedoo
 * @since 2021-4-1 10:40:52
 */
@Intercepts({
        @Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class),
})
@ConditionalOnProperty(value = "domain.encrypt", havingValue = "true")
@Component
@Slf4j
public class ParammeterInterceptor  implements Interceptor {
    @Autowired
    private IEncryptDecrypt encryptDecrypt;
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //拦截 ParameterHandler 的 setParameters 方法 动态设置参数
        if (invocation.getTarget() instanceof ParameterHandler) {
            ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();
            PreparedStatement ps = (PreparedStatement) invocation.getArgs()[0];
            // 反射获取 参数对像
            Field parameterField =
                    parameterHandler.getClass().getDeclaredField("parameterObject");
            parameterField.setAccessible(true);
            Object parameterObject = parameterField.get(parameterHandler);
            if (Objects.nonNull(parameterObject)) {
                Class<?> parameterObjectClass = parameterObject.getClass();
                EncryptDecryptClass encryptDecryptClass = AnnotationUtils.findAnnotation(parameterObjectClass, EncryptDecryptClass.class);
                if (Objects.nonNull(encryptDecryptClass)) {
                    Field[] declaredFields = parameterObjectClass.getDeclaredFields();
                    final Object encrypt = encryptDecrypt.encrypt(declaredFields, parameterObject);
                }
                /**
                 * 通过加密字段查询时, 将查询参数中的加密字段加密后查询
                 */
                if(parameterObjectClass == MapperMethod.ParamMap.class) {
                    MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) parameterObject;
                    boolean encrypted = false;
                    try{
                        /**
                         * 分页插件,会再分页查询时 进行多次查询,需要判断是否已对加密参数加密,防止多次加密后,查询失败
                         */
                        encrypted = paramMap.get("encrypted")!=null;
                    }catch (BindingException be){
                        encrypted = false;
                    }
                    if(!encrypted) {
                        Iterator iterator = paramMap.entrySet().iterator();
                        while(iterator.hasNext()){
                            Map.Entry<String, Object> entry = (Map.Entry<String, Object>) iterator.next();
                            if (entry.getKey().startsWith("param")) {
                                Object v = entry.getValue();
                                EncryptQueryClass encryptQueryClass = AnnotationUtils.findAnnotation(v.getClass(), EncryptQueryClass.class);
                                if (Objects.nonNull(encryptQueryClass)) {
                                    Field[] declaredFields = v.getClass().getDeclaredFields();
                                    for (Field field : declaredFields) {
                                        if (field.isAnnotationPresent(EncryptQuery.class)) {
                                            try {
                                                final Object encrypt = encryptDecrypt.encrypt(new Field[]{field}, v);
                                                paramMap.put("encrypted", true);
                                            } catch (IllegalAccessException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }
    @Override
    public void setProperties(Properties properties) {
    }
}
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/model/helper/encrypt/ResultInterceptor.java
New file
@@ -0,0 +1,75 @@
package com.panzhihua.service_community.model.helper.encrypt;
import com.panzhihua.common.model.helper.encrypt.EncryptDecryptClass;
import com.panzhihua.common.model.helper.encrypt.IEncryptDecrypt;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Properties;
/**
 * 解密拦截器
 *
 * @author cedoo
 * @since 2021-4-1 10:40:52
 */
@Intercepts({
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args={Statement.class})
})
@ConditionalOnProperty(value = "domain.decrypt", havingValue = "true")
@Component
@Slf4j
public class ResultInterceptor implements Interceptor {
    @Autowired
    private IEncryptDecrypt encryptDecrypt;
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object result = invocation.proceed();
        if (Objects.isNull(result)){
            return null;
        }
        if (result instanceof ArrayList) {
            ArrayList resultList = (ArrayList) result;
            if (resultList!=null && resultList.size()>0 && needToDecrypt(resultList.get(0))){
                for (int i = 0; i < resultList.size(); i++) {
                    encryptDecrypt.decrypt(resultList.get(i));
                }
            }
        }else {
            if (needToDecrypt(result)){
                encryptDecrypt.decrypt(result);
            }
        }
        return result;
    }
    public boolean needToDecrypt(Object object){
        Class<?> objectClass = object.getClass();
        EncryptDecryptClass encryptDecryptClass = AnnotationUtils.findAnnotation(objectClass, EncryptDecryptClass.class);
        if (Objects.nonNull(encryptDecryptClass)){
            return true;
        }
        return false;
    }
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties) {
    }
}
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/model/helper/sensitive/SensitiveInterceptor.java
New file
@@ -0,0 +1,71 @@
package com.panzhihua.service_community.model.helper.sensitive;
import com.panzhihua.common.model.helper.sensitive.Sensitive;
import com.panzhihua.common.model.helper.sensitive.SensitiveStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.stream.Stream;
/**
 * 字段脱敏拦截器
 * @author cedoo
 * @since 2021-4-1 10:40:52
 */
@Intercepts(@Signature(type = ResultSetHandler.class,
        method = "handleResultSets",
        args = {Statement.class}))
@Slf4j
@ConditionalOnProperty(value = "domain.sensitive", havingValue = "true")
@Component
public class SensitiveInterceptor implements Interceptor {
    @SuppressWarnings("unchecked")
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //log.debug("脱敏拦截器");
        List<Object> records = (List<Object>) invocation.proceed();
        // 对结果集脱敏
        records.forEach(this::sensitive);
        return records;
    }
    private void sensitive(Object source) {
        // 拿到返回值类型
        Class<?> sourceClass = source.getClass();
        // 初始化返回值类型的 MetaObject
        MetaObject metaObject = SystemMetaObject.forObject(source);
        // 捕捉到属性上的标记注解 @Sensitive 并进行对应的脱敏处理
        Stream.of(sourceClass.getDeclaredFields())
                .filter(field -> field.isAnnotationPresent(Sensitive.class))
                .forEach(field -> doSensitive(metaObject, field));
    }
    private void doSensitive(MetaObject metaObject, Field field) {
        // 拿到属性名
        String name = field.getName();
        // 获取属性值
        Object value = metaObject.getValue(name);
        // 只有字符串类型才能脱敏  而且不能为null
        if (String.class == metaObject.getGetterType(name) && value != null) {
            Sensitive annotation = field.getAnnotation(Sensitive.class);
            // 获取对应的脱敏策略 并进行脱敏
            SensitiveStrategy type = annotation.strategy();
            Object o = type.getDesensitizer().apply((String) value);
            // 把脱敏后的值塞回去
            metaObject.setValue(name, o);
        }
    }
}
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/resources/bootstrap.yml
@@ -21,6 +21,10 @@
    service-url:
      defaultZone: http://${EUREKA_URL:localhost}:8192/eureka
#实体加密、解密、字段脱敏拦截设置
domain:
  decrypt: true
  encrypt: true
  aesKey: Ryo7M3n8loC5
  sensitive: true