SpringBoot自定义注解之脱敏注解的示例分析(springboot,开发技术)

时间:2024-05-04 07:12:43 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

    自定义注解之脱敏注解

    数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。需求是把返回到前端的数据进行脱敏,以免造成隐私信息的泄露。

    一、脱敏后的效果

    SpringBoot自定义注解之脱敏注解的示例分析

    这样显示很不好吧,所有信息都泄露了

    SpringBoot自定义注解之脱敏注解的示例分析

    这样就很好了吧

    二、代码

    1.脱敏注解
    @Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)@JacksonAnnotationsInside@JsonSerialize(using=SensitiveSerialize.class)public@interfaceSensitive{/***脱敏数据类型*/SensitiveTypeEnumtype()defaultSensitiveTypeEnum.CUSTOMER;/***前置不需要打码的长度*/intprefixNoMaskLen()default0;/***后置不需要打码的长度*/intsuffixNoMaskLen()default0;/***用什么打码*/Stringsymbol()default"*";}
    2.定义脱敏类型
    publicenumSensitiveTypeEnum{/***自定义*/CUSTOMER,/***姓名*/NAME,/***身份证*/ID_NUM,/***手机号码*/PHONE_NUM}
    3.敏感工具类
    publicclassDesensitizedUtils{/***对字符串进行脱敏操作**@paramorigin原始字符串*@paramprefixNoMaskLen左侧需要保留几位明文字段*@paramsuffixNoMaskLen右侧需要保留几位明文字段*@parammaskStr用于遮罩的字符串,如'*'*@return脱敏后结果*/publicstaticStringdesValue(Stringorigin,intprefixNoMaskLen,intsuffixNoMaskLen,StringmaskStr){if(origin==null){returnnull;}StringBuildersb=newStringBuilder();for(inti=0,n=origin.length();i<n;i++){if(i<prefixNoMaskLen){sb.append(origin.charAt(i));continue;}if(i>(n-suffixNoMaskLen-1)){sb.append(origin.charAt(i));continue;}sb.append(maskStr);}returnsb.toString();}/***【中文姓名】只显示最后一个汉字,其他隐藏为星号,比如:**梦**@paramfullName姓名*@return结果*/publicstaticStringchineseName(StringfullName){if(fullName==null){returnnull;}returndesValue(fullName,1,0,"*");}/***【身份证号】显示前4位,后2位,其他隐藏。**@paramid身份证号码*@return结果*/publicstaticStringidCardNum(Stringid){returndesValue(id,4,2,"*");}/***【手机号码】前三位,后四位,其他隐藏。**@paramnum手机号码*@return结果*/publicstaticStringmobilePhone(Stringnum){returndesValue(num,3,4,"*");}}
    4.脱敏序列化信息
    @NoArgsConstructor@AllArgsConstructorpublicclassSensitiveSerializeextendsJsonSerializer<String>implementsContextualSerializer{/***脱敏类型*/privateSensitiveTypeEnumsensitiveTypeEnum;/***前几位不脱敏*/privateIntegerprefixNoMaskLen;/***最后几位不脱敏*/privateIntegersuffixNoMaskLen;/***用什么打码*/privateStringsymbol;@Overridepublicvoidserialize(finalStringorigin,finalJsonGeneratorjsonGenerator,finalSerializerProviderserializerProvider)throwsIOException{switch(sensitiveTypeEnum){caseCUSTOMER:jsonGenerator.writeString(DesensitizedUtils.desValue(origin,prefixNoMaskLen,suffixNoMaskLen,symbol));break;caseNAME:jsonGenerator.writeString(DesensitizedUtils.chineseName(origin));break;caseID_NUM:jsonGenerator.writeString(DesensitizedUtils.idCardNum(origin));break;casePHONE_NUM:jsonGenerator.writeString(DesensitizedUtils.mobilePhone(origin));break;default:thrownewIllegalArgumentException("unknownsensitivetypeenum"+sensitiveTypeEnum);}}@OverridepublicJsonSerializer<?>createContextual(finalSerializerProviderserializerProvider,finalBeanPropertybeanProperty)throwsJsonMappingException{if(beanProperty!=null){if(Objects.equals(beanProperty.getType().getRawClass(),String.class)){Sensitivesensitive=beanProperty.getAnnotation(Sensitive.class);if(sensitive==null){sensitive=beanProperty.getContextAnnotation(Sensitive.class);}if(sensitive!=null){returnnewSensitiveSerialize(sensitive.type(),sensitive.prefixNoMaskLen(),sensitive.suffixNoMaskLen(),sensitive.symbol());}}returnserializerProvider.findValueSerializer(beanProperty.getType(),beanProperty);}returnserializerProvider.findNullValueSerializer(null);}}

    小结一下

    该注解用于隐私数据的脱敏,只作用于类的属性上。该注解有四个属性,type表示脱敏数据类型(默认为CUSTOMER自定义,后面三个属性才有效),prefixNoMaskLen表示前置不需要打码的长度(默认为0),suffixNoMaskLen表示后置不需要打码的长度(默认为0),symbol表示用什么打码(默认为*)。

    一般用于返回对象给前端对象中包含隐私数据例如身份证、详细地址需要进行脱敏的情况。

    示例:

    publicclassUserInfo{@Sensitive(type=SensitiveTypeEnum.NAME)privateStringname;@Sensitive(type=SensitiveTypeEnum.ID_NUM)privateStringidNum;@Sensitive(type=SensitiveTypeEnum.PHONE_NUM)privateStringphone;@Sensitive(type=SensitiveTypeEnum.CUSTOMER,prefixNoMaskLen=3,suffixNoMaskLen=2,symbol="#")privateStringaddress;@Sensitive(prefixNoMaskLen=1,suffixNoMaskLen=2,symbol="*")privateStringpassword;}

    如果还有疑问我写了个demo,可以下载下来运行看看

    链接: 脱敏注解demo.

    自己手写的一个高效自定义字符串脱敏注解

    经理要求写一个自定义脱敏注解,百度查了一堆。都是效率比较低的

    自己写了个 仅供参考

    /***description:数据脱敏*1、默认不传部位、不传显示*号数量时字段全部脱敏**原始字符串adminis总长度从0计算总数6*index=(0,2)size=1下标即从0到2以内的字符标注“*”,size=1则只填充一个*size不能超过截取字符*index=(2,3)size=2下标即从2到3以内的字符标注“*”,size=2则只填充二个*size不能超过截取字符**date:2020/3/1315:56**@authoroakdog*@version1.0*/@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotationsInside@JsonSerialize(using=Desensitization.ConvertDesensitization.class)public@interfaceDesensitization{/*** 传入的下标索引* 规则第一位起始下标第二位是结束下标默认值6位下标**/int[]index()default{0,6};/*** 需要脱敏的字符长度* 规则输入3:则根据index下标索引对应脱敏3个字符默认6个长度脱敏**/intsize()default6;classConvertDesensitizationextendsStdSerializer<Object>implementsContextualSerializer{privateint[]index;privateintsize;publicConvertDesensitization(){super(Object.class);}privateConvertDesensitization(int[]index,intsize){super(Object.class);this.size=size;this.index=index;}@Overridepublicvoidserialize(Objectvalue,JsonGeneratorjgen,SerializerProviderprovider)throwsIOException{char[]str=value.toString().toCharArray();StringBuilderbuilder=newStringBuilder();Stringchar1=(String)value;if(str.length>0){//字符长度超长处理if(index[0]<str.length&&index[1]<str.length){//使用默认初始值的脱敏处理if(index[0]==0){//如果输入脱敏大小长度小于0或大于原始脱敏字符长度,则全脱敏字符if(size<0||size<str.length){char[]charStr=char1.substring(index[1],str.length).toCharArray();char[]charStr1=char1.substring(index[0],index[1]).toCharArray();builder.append(charStr1);for(inti=0;i<charStr.length;i++){if(size>i){builder.append("*");}else{builder.append(charStr[i]);}}}else{builder.append(getDefaultChar((String)value,"left"));}}else{//从中间位置截取脱敏处理//如果输入脱敏大小长度小于0或大于原始脱敏字符长度,则全脱敏字符if(size<0||size<str.length){char[]charStr=char1.substring(index[0],str.length-index[1]+1).toCharArray();//26-42//中间截取部分List<Integer>prefix=getPrefix(index[0],(String)value);//List<Integer>suffix=getSuffix(index[0],index[1],(String)value);for(Integerinteger:prefix){builder.append(str[integer]);}for(inti=0;i<charStr.length;i++){if(size>i){builder.append("*");}else{builder.append(charStr[i]);}}char[]chars=Arrays.copyOfRange(str,index[1],str.length);builder.append(String.valueOf(chars));}else{builder.append(getDefaultChar((String)value,"right"));}}}else{//默认处理builder.append(getDefaultChar((String)value,""));}}jgen.writeString(builder.toString());}/***默认的填充方式*@paramstr原始字符串*@paramposition位置*@return*/StringgetDefaultChar(Stringstr,Stringposition){char[]desensitizationStr=str.toCharArray();for(inti=0;i<desensitizationStr.length;i++){if("left".equals(position)){if(i!=0){desensitizationStr[i]='*';}}elseif("right".equals(position)){if(i!=desensitizationStr.length-1){desensitizationStr[i]='*';}}else{if(i!=0&&i!=desensitizationStr.length-1){desensitizationStr[i]='*';}}}returnString.valueOf(desensitizationStr);}/***获取字符前缀下标*@paramindex下标*@paramval原始字符串*@return*/List<Integer>getPrefix(intindex,Stringval){//int[]chars={};List<Integer>listIndex=newArrayList<>();for(inti=0;i<val.length();i++){if(i!=index){//01!=2listIndex.add(i);continue;}break;}returnlistIndex;}@OverridepublicJsonSerializer<?>createContextual(SerializerProviderprov,BeanPropertyproperty){int[]index={0,6};//初始值intsize=6;//初始值Desensitizationann=null;if(property!=null){ann=property.getAnnotation(Desensitization.class);}if(ann!=null){index=ann.index();size=ann.size();}returnnewDesensitization.ConvertDesensitization(index,size);}}}
     </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
    本文:SpringBoot自定义注解之脱敏注解的示例分析的详细内容,希望对您有所帮助,信息来源于网络。
    上一篇:如何使用自定义Json注解实现输出日志字段脱敏下一篇:

    8 人围观 / 0 条评论 ↓快速评论↓

    (必须)

    (必须,保密)

    阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18