需求竟然是全服务的数据脱敏!

一、背景:

公司因为数据安全需要做数据的脱敏,然而涉及的范围是全服务器!个别字段脱敏很快,影响整个服务的脱敏要一个一个的加我宁愿嘎!

二、解决方案:

1、一个一个加到死。


2、AOP一劳永逸。


三、设计思路


由于业务复杂,返回的对象里可能会含有多种脱敏规则的字段,且对象里同一脱敏规则下可能会含有多个需要脱敏的字段,所以设计DesensitizationEnum枚举类来解决此问题(主要是防止需求变更突然多几个字段要脱敏),并返回列表原对象类型(如果不是多层嵌套可用反射解决该问题),方便导出时列表查询接口的复用。
eg:
{
    "userName": "测试",
    "userName1": "测试1",
    "userName2": "测试2",
    "userName3": "测试3"
}

四、代码展现


枚举类


@Getter
public enum DesensitizationEnum {

    /**
     * 手机号脱敏                        中间4位
     */
    MOBILE_PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1*****$2"), new String[]{"mobileNumber","phoneNumber", "phone", "mobile"}),

    /**
     * 名称、对方账户             只保留姓
     */
    USER_NAME(s -> s.substring(0, 1) + s.substring(1).replaceAll("\\S", "*"), new String[]{"userName", "userName1", "userName2", "userName3"}),

    /**
     * 身份证                              保留前六位和后四位
     */
    PERSON_ID_CARD(s -> s.replaceAll("(\\d{6})\\d*(\\d{4})", "$1********$2"), new String[]{"personIdCard"}),

    /**
     * 邮箱                               @之前都脱敏
     */
    EMAIL(s -> s.replaceAll("(.*)@", "******@"), new String[]{"email", "mchtEmail"}),

    /**
     * 商户ID 商户key                     包留前4位
     */
    MCH(s -> s.replaceAll("(.{4}).*", "$1*****"), new String[]{"mchId"}),

    /**
     * 地址脱敏                              省略后5位
     */
    ADDRESS(s -> s.replaceAll("(.{5})$", "*****"), new String[]{"address", "recipientAddress"}),

    /**
     *  全都脱敏
     */
    PASSWORD(s -> s.replaceAll("\\S", "*"), new String[]{"password"}),

    /**
     *   保留前6位
     */
    ROOT_ACC_NO(s -> s.replaceAll("(\\d{6})\\d*", "$1************"), new String[]{"rootAccNo"})
    ;

    /**
     * 成员变量  是一个接口类型
     */
    private Function<String, String> function;
    private String[] field;

    DesensitizationEnum(Function<String, String> function, String[] field) {
        this.function = function;
        this.field = field;
    }

    public Function<String, String> function() {
        return this.function;
    }

    public static String getApply(DesensitizationEnum desensitizationEnum, Object str) {
        if (!ObjectUtils.allNotNull(str) || StringUtils.isBlank(str.toString())) {
            return "";
        }
        return desensitizationEnum.getFunction().apply(str.toString());
    }
}

注解类

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DesensitizationAnnotation {
    DesensitizationEnum[] desensitizationEnum();

    Class resultClz();
}

切面类

@Slf4j
@Aspect
@Component
public class DesensitizationAnnotationAspect {

    @Around("@annotation(desensitizationAnnotation)")
    public Object around(ProceedingJoinPoint jp, DesensitizationAnnotation desensitizationAnnotation) throws Throwable {

        Object proceed = jp.proceed();

        try {
            if (!ObjectUtils.allNotNull(proceed)) {
                return proceed;
            }
            log.info("脱敏原数据为:[{}]", proceed);
            JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONStringWithDateFormat(proceed, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat));
            List resultListJson = JSONObject.parseObject(jsonObject.get("resultList").toString(), List.class);
            List resultList = Lists.newArrayList();

            if (CollectionUtils.isEmpty(resultListJson)) {
                return proceed;
            }

            resultListJson.stream().forEach(list -> {
                JSONObject listJsonObject = JSONObject.parseObject(list.toString());
                DesensitizationEnum[] desensitizationEnums = desensitizationAnnotation.desensitizationEnum();
                Arrays.stream(desensitizationEnums).sorted().forEach(desensitizationEnum -> {
                    Arrays.stream(desensitizationEnum.getField()).sorted().forEach(field -> {
                        if (ObjectUtils.allNotNull(listJsonObject.get(field)) && StringUtils.isNotBlank(listJsonObject.get(field).toString())) {
                            String str = listJsonObject.get(field).toString();
                            String apply = desensitizationEnum.function().apply(str);
                            listJsonObject.put(field, apply);
                        }
                    });
                });
                resultList.add(listJsonObject);
            });
            List result = JSONObject.parseArray(JSON.toJSONString(resultList), desensitizationAnnotation.resultClz());
            jsonObject.put("resultList", result);
            if (ObjectUtils.allNotNull(jsonObject)) {
                PageQueryDto pageQueryDto = (PageQueryDto)proceed;
                pageQueryDto.setResultList(result);
                proceed = pageQueryDto;
            }
        } catch (Exception e) {
            log.error("DesensitizationAnnotationAspect error:", e);
            return proceed;
        }
        log.info("脱敏后数据为:[{}]", proceed);
        return proceed;
    }

}

五、Demo展现


Demo

    @DesensitizationAnnotation(desensitizationEnum = {DesensitizationEnum.USER_NAME, DesensitizationEnum.MOBILE_PHONE, DesensitizationEnum.ROOT_ACC_NO, DesensitizationEnum.MCH, DesensitizationEnum.PERSON_ID_CARD}, resultClz = testDto.class)
    @Override
    public void testDesensitization() {

       
        return ;

    }

												————  What is worth doing is worth doing well.
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值