SpringBoot中对于字符串进行脱敏操作

2020-11-04  本文已影响0人  LOC_Thomas

问题

在电商业务中,对于一些敏感数据(比如 用户姓名,用户身份证,用户手机号码,用户银行卡等),需要进行脱敏操作,为了业务开发的方便,应该要提供对应的处理方法, 能够使得业务开发能够自由的配置。

方案

所以采取了和之前文章中,我们采取的方案是,重新修改默认的ObjectMapper对象,添加一个自定义类型的DesensitizationBeanSerializerModifier,通过对于所有的String字符串都进行过滤,并且提供了 对应的注解 Desensitization,和一些参数, 可以根据不同的脱敏规则进行自由的配置

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
public @interface Desensitization {

  //前后分别展示多少个字符
  int showPrefixLength() default 3;
  int showSuffixLength() default 4;

  //针对长度进行多种处理,0为不考虑长度
  int strLength() default 0;

}

下面为自己定义的序列化方法

public static class DesensitizationBeanSerializerModifier extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
        BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
      for (Object beanProperty : beanProperties) {
        BeanPropertyWriter writer = (BeanPropertyWriter) beanProperty;
        if (isStringType(writer)) {
          Desensitization desensitization = ((BeanPropertyWriter) beanProperty).getAnnotation(Desensitization.class);
          Desensitizations desensitizations = ((BeanPropertyWriter) beanProperty).getAnnotation(Desensitizations.class);
          if (desensitization != null || desensitizations != null) {
            StringDesensitizationJsonSerializer stringDesensitizationJsonSerializer = new StringDesensitizationJsonSerializer();
            if (desensitization != null) {
              stringDesensitizationJsonSerializer.setDesensitization(desensitization);
            }
            if (desensitizations != null) {
              stringDesensitizationJsonSerializer.setDesensitizations(desensitizations);
            }

            writer.assignSerializer(stringDesensitizationJsonSerializer);
          }
        }
      }
      return beanProperties;
    }

    /**
     * 是否是string
     */
    private boolean isStringType(BeanPropertyWriter writer) {
      Class<?> clazz = writer.getType().getRawClass();
      return CharSequence.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz);
    }

  }

具体的针对脱敏注解的逻辑操作

/**
  * 处理字符串脱敏处理
  */
 @NoArgsConstructor
 @AllArgsConstructor
 public static class StringDesensitizationJsonSerializer extends JsonSerializer<Object> {

   @Setter
   private Desensitization desensitization;
   @Setter
   private Desensitizations desensitizations;

   @Override
   public void serialize(Object o, JsonGenerator jsonGenerator,
       SerializerProvider serializerProvider) throws IOException {
     if (desensitization == null && desensitizations == null) {
       return;
     }
     Desensitization[] desensitizationArray = getDesensitizationArray();
     String value = o.toString();

     int valueLength = value.length();
     boolean matchSize = false;
     int zeroLength = -1;
     int index = 0;
     for (Desensitization desensitization : desensitizationArray) {
       if (valueLength == desensitization.strLength()) {
         matchSize = true;
         jsonGenerator
             .writeString(fixedVal(value, desensitization.showPrefixLength(), desensitization.showSuffixLength()));
       } else if (desensitization.strLength() == 0 && zeroLength == -1) {
         zeroLength = index++;
       } else {
         index++;
       }
     }

     if (!matchSize) {
       if(zeroLength != -1) {
         jsonGenerator
             .writeString(fixedVal(value, desensitizationArray[zeroLength].showPrefixLength(),
                 desensitizationArray[zeroLength].showSuffixLength()));
       } else {
         jsonGenerator
             .writeString(fixedVal(value, desensitizationArray[0].showPrefixLength(),
                 desensitizationArray[0].showSuffixLength()));
       }
     }

   }

   private Desensitization[] getDesensitizationArray() {
     int size = 0;
     if (desensitization != null) {
       size++;
     }

     if (desensitizations != null) {
       size += desensitizations.value().length;
     }

     Desensitization[] desensitizationArray = new Desensitization[size];
     int index = 0;
     if (desensitization != null) {
       desensitizationArray[index++] = desensitization;
     }

     if (desensitizations != null) {
       System.arraycopy(desensitizations.value(), 0, desensitizationArray, index, size - index);
     }
     return desensitizationArray;
   }

   private String fixedVal(String value, int prefixLength, int suffixLength) {
     if (StringUtils.isBlank(value)) {
       return Strings.repeat("*", value.length());
     }

     if(value.length() <= prefixLength + suffixLength) {
       return value;
     }
     int length = value.length();
     String prefix = value.substring(0, prefixLength);
     String suffix = value.substring(length - suffixLength);
     String stars = Strings.repeat("*", length - (prefixLength + suffixLength));
     return prefix + stars + suffix;
   }
 }

这样对于一个Bean里面的对象,都可以进行相关操作。

下面给一个例子


@Data
public class DesensitizationsBean {

  @Desensitizations(value = {
      @Desensitization(strLength = 4, showPrefixLength = 2, showSuffixLength = 1),
      @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
      @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
      @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
  })
  private String mobileA;
  @Desensitizations(value = {
      @Desensitization,
      @Desensitization(strLength = 1, showPrefixLength = 0, showSuffixLength = 1),
      @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
      @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
      @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
  })
  private String mobileB;
  @Desensitizations(value = {
      @Desensitization,
      @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
      @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
      @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
      @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
  })
  private String mobileC;
  @Desensitizations(value = {
      @Desensitization,
      @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
      @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
      @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
      @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
  })
  private String mobileD;
  @Desensitizations(value = {
      @Desensitization,
      @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
      @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
      @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
      @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
  })
  private String mobileE;
  @Desensitizations(value = {
      @Desensitization,
      @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
      @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
      @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
      @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
  })
  private String mobileF;
  private List<DesensitizationsSubBean> subBeanList;

  @Data
  @Builder
  @NoArgsConstructor
  @AllArgsConstructor
  public static class DesensitizationsSubBean {

    @Desensitizations(value = {
        @Desensitization,
        @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
        @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
        @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
        @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
    })
    private Long mobile1;
    @Desensitizations(value = {
        @Desensitization,
        @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
        @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
        @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
        @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
    })
    private String mobile2;
    @Desensitizations(value = {
        @Desensitization,
        @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
        @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
        @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
        @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
    })
    private String mobile3;
    @Desensitizations(value = {
        @Desensitization,
        @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
        @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
        @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
        @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
    })
    private String mobile4;
    @Desensitizations(value = {
        @Desensitization,
        @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
        @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
        @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
        @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
    })
    private String mobile5;
    @Desensitizations(value = {
        @Desensitization,
        @Desensitization(strLength = 1, showPrefixLength = 1, showSuffixLength = 1),
        @Desensitization(strLength = 2, showPrefixLength = 1, showSuffixLength = 0),
        @Desensitization(strLength = 3, showPrefixLength = 0, showSuffixLength = 1),
        @Desensitization(strLength = 4, showPrefixLength = 1, showSuffixLength = 1),
    })
    private String mobile6;
  }
}


@GetMapping("/desensitizations")
  public BaseResult desensitizations() {
    DesensitizationsBean desensitizationsBean = new DesensitizationsBean();
    desensitizationsBean.setMobileA("18507313226");
    desensitizationsBean.setMobileB("龙");
    desensitizationsBean.setMobileC("龙哲");
    desensitizationsBean.setMobileD("龙若妍");
    desensitizationsBean.setMobileE("龙若妍好");
    desensitizationsBean.setMobileF("18507313226");

    desensitizationsBean.setSubBeanList(
        Lists.newArrayList(
            DesensitizationsSubBean.builder().mobile1(18507313226L).mobile2("龙").mobile3("龙哲").mobile4("龙若妍").mobile5("龙若妍好").mobile6("18507313226").build(),
            DesensitizationsSubBean.builder().mobile1(18507313226L).mobile2("龙").mobile3("龙哲").mobile4("龙若妍").mobile5("龙若妍好").mobile6("18507313226").build(),
            DesensitizationsSubBean.builder().mobile1(18507313226L).mobile2("龙").mobile3("龙哲").mobile4("龙若妍").mobile5("龙若妍好").mobile6("18507313226").build()
        ));

    return BaseResult.success(desensitizationsBean);
  }

执行的结果是

{
  "code": 0,
  "msg": "success",
  "traceId": "6ba0c884b10fbd8f",
  "data": {
    "mobileA": "18********6",
    "mobileB": "龙",
    "mobileC": "龙*",
    "mobileD": "**妍",
    "mobileE": "龙**好",
    "mobileF": "185****3226",
    "subBeanList": [
      {
        "mobile1": 18507313226,
        "mobile2": "龙",
        "mobile3": "龙*",
        "mobile4": "**妍",
        "mobile5": "龙**好",
        "mobile6": "185****3226"
      },
      {
        "mobile1": 18507313226,
        "mobile2": "龙",
        "mobile3": "龙*",
        "mobile4": "**妍",
        "mobile5": "龙**好",
        "mobile6": "185****3226"
      },
      {
        "mobile1": 18507313226,
        "mobile2": "龙",
        "mobile3": "龙*",
        "mobile4": "**妍",
        "mobile5": "龙**好",
        "mobile6": "185****3226"
      }
    ]
  }
}

这样业务放就只要简单的在想要脱敏的字段上加入对应的注解和配置对应的参数就可以了。

结束

转载请注明作者和出处,并添加本页链接。
原文链接: //tech.cnhnb.com/post/6

上一篇 下一篇

猜你喜欢

热点阅读