通过拦截器实现返回数据脱敏处理示例

  1. 定义一个枚举类,用于指定不同的脱敏类型,如手机号、身份证
     
    /**
     * desc定义一个枚举类,用于指定不同的脱敏类型,比如手机号、身份证号等
     *
     * @author wcl
     */
    public enum SensitiveDataType {
        MOBILE,
        ID_CARD,
        EMAIL,
        ADDRESS
    }
  2. 创建一个自定义注解,用于标记需要脱敏的字段
     
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    /**
     * desc 创建一个自定义注解,用于标记需要脱敏的字段
     *
     * @author date
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SensitiveData {
        SensitiveDataType type();
    }
    
  3. 创建一个切面类,用于对返回值进行脱敏处理
     
    /**
     * @Description: 创建一个切面类,用于对返回值进行脱敏处理
     * @author: wcl
     * @date: 2025-02-14 13:25
     */
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.Collection;
    
    /**
     * desc 定义脱敏切面
     * @author wcl
     * @date 2025/2/14 14:37
     **/
    @Aspect
    @Component
    public class DesensitizeAspect {
    
        @Around("execution(* com.esop.resurge.dataetlsystem.controller..*(..))")
        public Object desensitize(ProceedingJoinPoint joinPoint) throws Throwable {
            Object result = joinPoint.proceed(); // 执行原有方法
    
            if (result == null) {
                return null;
            }
    
            if (result instanceof Collection<?>) { // 处理集合类型返回值
                Collection<?> collection = (Collection<?>) result;
                Collection<Object> desensitizedCollection = new ArrayList<>(collection.size());
                for (Object item : collection) {
                    try {
                        desensitizedCollection.add(desensitizeObject(item));
                    } catch (Exception e) {
                        // 记录日志或采取其他措施处理异常
                        desensitizedCollection.add(item); // 或者可以选择跳过该元素
                    }
                }
                return desensitizedCollection;
            } else if (result.getClass().isArray()) { // 处理数组类型返回值
                Object[] array = (Object[]) result;
                Object[] desensitizedArray = new Object[array.length];
                for (int i = 0; i < array.length; i++) {
                    try {
                        desensitizedArray[i] = desensitizeObject(array[i]);
                    } catch (Exception e) {
                        // 记录日志或采取其他措施处理异常
                        desensitizedArray[i] = array[i]; // 或者可以选择跳过该元素
                    }
                }
                return desensitizedArray;
            } else { // 处理单一对象返回值
                try {
                    return desensitizeObject(result);
                } catch (Exception e) {
                    // 记录日志或采取其他措施处理异常
                    return result; // 或者可以选择抛出异常
                }
            }
        }
    
    
        private Object desensitizeObject(Object obj) {
            if (obj != null) {
                Class<?> clazz = obj.getClass();
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    if (field.isAnnotationPresent(SensitiveData.class)) {
                        // 获取字段的注解
                        SensitiveData annotation = field.getAnnotation(SensitiveData.class);
                        SensitiveDataType type = annotation.type();
                        field.setAccessible(true); // 设置私有字段可访问
                        try {
                            // 进行脱敏处理,例如替换为星号等
                            field.set(obj, setSensitiveData(type, field.get(obj))); // 示例代码,实际应实现脱敏逻辑
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            return obj;
        }
    
        private Object setSensitiveData(SensitiveDataType type, Object obj) {
                if (obj == null) {
                    return null;
                }
                if(type == null){
                    return obj;
                }
                String value = String.valueOf(obj);
                switch (type) {
                    case MOBILE:
                        obj=maskMobile(value);
                        break;
                    case ID_CARD:
                        obj=maskIdCard(value);
                        break;
                    case EMAIL:
                        obj=maskEmail(value);
                        break;
                    case ADDRESS:
                        obj=maskAddress(value);
                        break;
                    default:
                        break;
                }
                return obj;
        }
    
        private String maskMobile(String mobile) {
            if (mobile == null || mobile.length() != 11) {
                return mobile;
            }
            return mobile.substring(0, 3) + "****" + mobile.substring(7);
        }
    
        private String maskIdCard(String idCard) {
            if (idCard == null || idCard.length() != 18) {
                return idCard;
            }
            return idCard.substring(0, 6) + "********" + idCard.substring(14);
        }
    
        private String maskEmail(String email) {
            if (email == null) {
                return email;
            }
            int atIndex = email.indexOf('@');
            if (atIndex == -1) {
                return email;
            }
            if (atIndex < 2) {
                return "****"+email.substring(atIndex);
            }
            StringBuffer sb=new StringBuffer("");
            String prefix = email.substring(0, 1);
            String suffix = email.substring(atIndex-1);
            String midStr = email.substring(1,atIndex-1);
            if(midStr!=null && midStr.length()>0){
                for(int i=0;i<midStr.length();i++){
                    sb.append("*");
                }
            }else{
                sb.append("*");
            }
            return prefix + sb + suffix;
        }
    
        private String maskAddress(String address) {
            if (address == null || address.length() < 4) {
                return address;
            }
            return address.substring(0, 2) + "****" + address.substring(address.length() - 2);
        }
    }
    
  4. 创建数据实体类,用于测试敏感数据脱敏
     
    /**
     * @Description: 创建数据实体类,用于测试敏感数据脱敏
     * @author: wcl
     * @date: 2025-02-14 13:04
     */
    public class User {
        private String name;
    
        @SensitiveData(type = SensitiveDataType.MOBILE)
        private String mobile;
    
        @SensitiveData(type = SensitiveDataType.ID_CARD)
        private String idCard;
    
        @SensitiveData(type = SensitiveDataType.EMAIL)
        private String email;
    
        @SensitiveData(type = SensitiveDataType.ADDRESS)
        private String address;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getMobile() {
            return mobile;
        }
    
        public void setMobile(String mobile) {
            this.mobile = mobile;
        }
    
        public String getIdCard() {
            return idCard;
        }
    
        public void setIdCard(String idCard) {
            this.idCard = idCard;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    
  5. 创建接口,测试敏感数据
     
    import com.esop.resurge.dataetlsystem.config.sensitive.User;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Description: 创建接口,测试敏感数据
     * @author: wcl
     * @date: 2025-02-14 13:06
     */
    @Api(value = "test", tags = {"test"})
    @RequestMapping("/test")
    @RestController
    public class UserController {
        @ApiOperation("test")
        @GetMapping("/user")
        public List<User> getUser() {
            User user = new User();
            user.setName("张三");
            user.setMobile("13800138000");
            user.setIdCard("11010519491231002X");
            user.setEmail("[email protected]");
            user.setAddress("北京市海淀区");
            User user2 = new User();
            user2.setName("张三2");
            user2.setMobile("18911112220");
            user2.setIdCard("11010519891231002X");
            user2.setEmail("[email protected]");
            user2.setAddress("北京市海淀区2");
            List<User> list=new ArrayList<>(2);
            list.add(user);
            list.add(user2);
            return list;
        }
    }
    
  6. 调用接口/test/user,查看接口返回,如下图,返回数据已脱敏