Java自定義注解實(shí)現(xiàn)數(shù)據(jù)脫敏
自定義注解實(shí)現(xiàn)數(shù)據(jù)脫敏,,國密加解密(sm4)
在實(shí)際開發(fā)中經(jīng)常會(huì)遇到有一些信息不能全部展示用戶,需要隱藏(可以叫脫敏)一部分的情況比如地址,電話,手機(jī)號(hào),身份證等。脫敏的做法目前我知道的方法有:
1):業(yè)務(wù)代碼脫敏:顧名思義就是拿到數(shù)據(jù)需要脫敏的那個(gè)字段進(jìn)過一系列的脫敏規(guī)則替換成自己想要的格式。
2):自定義注解+aop切面的方式去完成字段脫敏的目的。
3):自定義注解+序列化的方式對數(shù)據(jù)進(jìn)行脫敏。
其中效率最慢的當(dāng)屬于代碼業(yè)務(wù)代碼方式,最優(yōu)的方式當(dāng)屬于自定義注解的方式,減少代碼量,提高工作效率,需要脫敏的字段僅需要加一個(gè)注解就可以達(dá)到目的。
今天就記錄下第三種方式,自定義注解+序列化的方式。
首先先定義一個(gè)需要脫敏的策略
/** * @description: 脫敏策略 * @author: * @date: 2023/6/18 19:45 * @Version: 1.0 */ public enum DesensitizationEnum { /** * 名稱脫敏 */ USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")) , /** * 手機(jī)號(hào)脫敏 */ MOBILE_PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")) , /** *地址脫敏 */ ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}", "$1****$2****")) ; /** * 成員變量 是一個(gè)接口類型 */ private Function<String, String> function; DesensitizationEnum(Function<String, String> function) { this.function = function; } public Function<String, String> function() { return this.function; } }
然后自定義一個(gè)注解
import com.chaozhou.test01.dingShiRenWu.Annontion.Aspect.DesensitizationEnum; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @description: * @author: * @date: 2023/6/18 17:23 * @Version: 1.0 */ @Target({ElementType.FIELD}) //表明作用在字段上 @Retention(RetentionPolicy.RUNTIME) //什么情況下生效 @JacksonAnnotationsInside //標(biāo)明序列化 @JsonSerialize(using = DesensitizationDataSerialize.class) public @interface DesensitizationData { DesensitizationEnum function(); }
然后自定義一個(gè)序列化器
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import lombok.NoArgsConstructor; import java.io.IOException; import java.util.Objects; /** * @description: 數(shù)據(jù)脫敏序列化器 * @author: * @date: 2023/6/18 19:17 * @Version: 1.0 */ @NoArgsConstructor public class DesensitizationDataSerialize extends JsonSerializer<String> implements ContextualSerializer { private DesensitizationEnum fuincation; @Override public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException { DesensitizationData annotation = beanProperty.getAnnotation(DesensitizationData.class); if(Objects.nonNull(annotation) && Objects.equals(beanProperty.getType().getRawClass(),String.class)){ this.fuincation = annotation.function(); return this; } return serializerProvider.findValueSerializer(beanProperty.getType(),beanProperty); } @Override public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeString(fuincation.function().apply(s)); } }
這樣一個(gè)自定義脫敏注解就完成了。
使用方法:
只需要在返回參數(shù)需要脫敏的字段上加上響應(yīng)注解就可以了
public class User implements Serializable { @TableId("id") private Integer id; @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") @ApiModelProperty(value = "出生年月") private Date birthday; @ApiModelProperty(value = "性別") private String gender; @ApiModelProperty(value = "姓名") private String username; @ApiModelProperty(value = "密碼") private String password; @ApiModelProperty(value = "備注") private String remark; @ApiModelProperty(value = "狀態(tài)") private String station; @ApiModelProperty(value = "聯(lián)系電話") //手機(jī)號(hào)脫敏 @DesensitizationData(function = DesensitizationEnum.MOBILE_PHONE) private String telephone; }
結(jié)果
手機(jī)號(hào)已經(jīng)脫敏成功,該方法單條,多條數(shù)據(jù)都支持。
國密加解密
需要用到的依賴,可以直接用hutool整合的框架實(shí)現(xiàn)
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.16</version> </dependency> <!--以下依賴不加親測也可以實(shí)現(xiàn)--> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.60</version> </dependency>
在以上方法中的策略中加入加解密規(guī)則
然后在需要加密或解密的字段中加入該注解,并注解標(biāo)注正確的策略方式
修改一下上面的序列化器,防止需要需要解密的字段值我空的時(shí)候報(bào)“Null input buffer”的錯(cuò)
列表字段加密前
列表加密后
工具準(zhǔn)備的好,代碼效率高了不少。
到此這篇關(guān)于Java自定義注解實(shí)現(xiàn)數(shù)據(jù)脫敏的文章就介紹到這了,更多相關(guān)Java數(shù)據(jù)脫敏內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Swagger3.0 整合spring boot2.7x避免swagger2.0與boot2.7沖突
這篇文章主要介紹了Swagger3.0 整合spring boot2.7x避免swagger2.0與boot2.7沖突問題,通過注釋掉2.0引入的倆包,直接引入3.0,文中結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10Java基于分治算法實(shí)現(xiàn)的線性時(shí)間選擇操作示例
這篇文章主要介紹了Java基于分治算法實(shí)現(xiàn)的線性時(shí)間選擇操作,涉及java排序、比較、計(jì)算等相關(guān)操作技巧,需要的朋友可以參考下2017-11-11詳解IDEA中SpringBoot整合Servlet三大組件的過程
這篇文章主要介紹了詳解IDEA中SpringBoot整合Servlet三大組件的過程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11java7鉆石語法知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理的是關(guān)于java7鉆石語法的相關(guān)知識(shí)點(diǎn)內(nèi)容,有需要的朋友們參考下。2019-11-11java數(shù)據(jù)結(jié)構(gòu)與算法之桶排序?qū)崿F(xiàn)方法詳解
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)與算法之桶排序?qū)崿F(xiàn)方法,結(jié)合具體實(shí)例形式詳細(xì)分析了桶排序的概念、原理、實(shí)現(xiàn)方法與相關(guān)操作技巧,需要的朋友可以參考下2017-05-05