文章目录

引言
一、接口数据脱敏概述
1.1 接口数据脱敏的定义
接口数据脱敏是指在web应用程序的api接口返回数据时,对包含敏感信息的字段进行处理,使其部分或全部信息被隐藏或替换,以防止敏感信息的泄露。这个过程通常不会改变数据的原始格式,而是通过特定的算法或规则,将敏感部分替换为特定字符(如星号*)或者保留部分信息。
1.2 接口数据脱敏的重要性
数据脱敏的重要性主要体现在以下几个方面:
- 保护用户隐私: 对于姓名、身份证号、手机号等个人敏感信息进行脱敏,可以有效保护用户隐私,防止信息被滥用。
- 遵守法律法规: 许多国家和地区都制定了严格的数据保护法规,如欧盟的gdpr和中国的《个人信息保护法》。实施数据脱敏有助于企业合规经营。
- 降低安全风险: 通过脱敏处理,即使数据不慎泄露,也能最大限度地减少敏感信息被盗用的风险。
- 支持数据共享: 在保护隐私的同时,脱敏数据仍然保留了一定的分析价值,有利于数据的安全共享和利用。
1.3 接口数据脱敏的实现方式
-
手动脱敏:在业务逻辑层直接对敏感数据进行处理。这种方式灵活但容易遗漏,且代码重复率高。
-
aop(面向切面编程):通过切面拦截返回数据,统一处理敏感字段。这种方式可以集中管理脱敏逻辑,但可能影响性能。
-
自定义序列化器:利用json序列化框架(如jackson)的自定义序列化器来处理敏感字段。这种方式性能较好,且与业务逻辑解耦。
-
注解+反射:通过自定义注解标记需要脱敏的字段,然后利用反射机制在运行时进行脱敏处理。这种方式使用简单,易于维护。
本文将重点介绍如何结合自定义注解和hutool工具类来实现接口数据脱敏。
二、开发环境
- jdk版本:jdk 17
- spring boot版本:spring boot 3.2.2
- 构建工具:maven
三、实现接口返回数据脱敏
3.1 添加依赖
首先在 pom.xml
文件中添加必要的依赖:
<!-- hutool工具包 -->
<dependency>
<groupid>cn.hutool</groupid>
<artifactid>hutool-all</artifactid>
<version>5.8.25</version>
</dependency>
<!-- jackson依赖 -->
<dependency>
<groupid>com.fasterxml.jackson.core</groupid>
<artifactid>jackson-databind</artifactid>
<version>2.9.2</version>
</dependency>
3.2 创建自定义注解
接下来,我们创建一个自定义注解 @desensitize
:
/**
* 用于标记字段需要进行脱敏处理的注解
*
* @author shijun
* @date 2024/07/09
*/
@retention(retentionpolicy.runtime)
@target(elementtype.field)
@jacksonannotationsinside
@jsonserialize(using = desensitizeserializer.class)
public @interface desensitize {
/**
* 脱敏类型
*/
desensitizetype type() default desensitizetype.default;
/**
* 脱敏起始位置
*/
int startinclude() default 0;
/**
* 脱敏结束位置
*/
int endexclude() default 0;
}
3.3 定义脱敏枚举类
然后,定义枚举类 desensitizetype
来定义字段的脱敏类型:
/**
* 脱敏类型枚举类
*/
public enum desensitizetype {
/**
* 默认脱敏
*/
default,
/**
* 自定义脱敏
*/
custom_rule,
/**
* 手机号脱敏
*/
phone,
/**
* 电子邮件脱敏
*/
email,
/**
* 身份证号脱敏
*/
id_card,
/**
* 银行卡号脱敏
*/
bank_card,
/**
* 地址脱敏
*/
address,
/**
* 中文姓名脱敏
*/
chinese_name,
/**
* 密码脱敏
*/
password,
}
3.4 创建自定义序列化类
/**
* 脱敏序列化器,用于在序列化字符串时根据不同的脱敏类型进行数据脱敏。
*
* @author shijun
* @date 2024/07/08
*/
public class desensitizeserializer extends jsonserializer<string> implements contextualserializer {
/**
* 脱敏类型,默认为default
*/
private desensitizetype type;
/**
* 脱敏起始位置
*/
private int startinclude;
/**
* 脱敏结束位置
*/
private int endexclude;
public desensitizeserializer() {
this.type = desensitizetype.default;
}
public desensitizeserializer(desensitizetype type) {
this.type = type;
}
/**
* 序列化字符串时调用,根据脱敏类型对字符串进行相应的脱敏处理。
*
* @param value 待序列化的字符串
* @param gen json生成器,用于写入处理后的字符串
* @param serializers 序列化器提供者,用于获取其他序列化器
* @throws ioexception 如果序列化过程中发生i/o错误
*/
@override
public void serialize(string value, jsongenerator gen, serializerprovider serializers) throws ioexception {
switch (type) {
case custom_rule:
// 这里是对字符串的startinclude到endexclude字段进行隐藏处理,如果想要实现两端保留,可以考虑使用strutil的replace方法
gen.writestring(strutil.hide(value, startinclude, endexclude));
break;
case phone:
gen.writestring(desensitizedutil.mobilephone(value));
break;
case email:
gen.writestring(desensitizedutil.email(value));
break;
case id_card:
gen.writestring(desensitizedutil.idcardnum(value, 1, 2));
break;
case bank_card:
gen.writestring(desensitizedutil.bankcard(value));
break;
case address:
gen.writestring(desensitizedutil.address(value, 8));
break;
case chinese_name:
gen.writestring(desensitizedutil.chinesename(value));
break;
case password:
gen.writestring(desensitizedutil.password(value));
break;
default:
gen.writestring(value);
break;
}
}
/**
* 根据上下文信息创建自定义的序列化器,用于处理带有@desensitize注解的属性。
*
* @param prov 序列化器提供者,用于获取其他序列化器
* @param property 当前属性的信息,用于获取注解和属性类型
* @return 自定义的序列化器实例
*/
@override
public jsonserializer<?> createcontextual(serializerprovider prov, beanproperty property) {
if (property != null) {
desensitize annotation = property.getannotation(desensitize.class);
if (annotation != null) {
this.type = annotation.type();
if (annotation.type() == desensitizetype.custom_rule) {
this.startinclude = annotation.startinclude();
this.endexclude = annotation.endexclude();
}
}
}
return this;
}
}
四、测试
4.1 编写测试代码
- 编写实体类
@data
public class userdto {
/**
* 用户姓名
*/
@desensitize(type = desensitizetype.chinese_name)
private string name;
/**
* 用户手机号
*/
@desensitize(type = desensitizetype.phone)
private string phonenumber;
/**
* 用户电子邮件地址
*/
@desensitize(type = desensitizetype.email)
private string email;
/**
* 用户密码
*/
@desensitize(type = desensitizetype.password)
private string password;
/**
* 用户身份证号码
*/
@desensitize(type = desensitizetype.id_card)
private string idcard;
/**
* 用户银行卡号
*/
@desensitize(type = desensitizetype.bank_card)
private string bankcard;
/**
* 用户地址
*/
@desensitize(type = desensitizetype.address)
private string address;
/**
* 游戏名称
*/
@desensitize(type = desensitizetype.custom_rule, startinclude = 2, endexclude = 6)
private string gamename;
}
- 编写测试接口
@restcontroller
@requestmapping("/test")
public class testcontroller {
@getmapping("/desensitize")
public userdto getuser() {
userdto userdto = new userdto();
userdto.setname("孙大圣");
userdto.setemail("shijun@163.com");
userdto.setphonenumber("12345678901");
userdto.setpassword("123456");
userdto.setaddress("辽宁省盘锦市兴隆台区红村乡441号");
userdto.setidcard("447465200912089605");
userdto.setbankcard("6217000000000000000");
userdto.setgamename("超级无敌大铁锤");
return userdto;
}
}
4.2 测试
五、总结
在本文中,我们探讨了在springboot应用程序中实现数据脱敏的重要性,并提出了通过自定义注解结合hutool脱敏工具类实现数据脱敏的解决方案。通过这个方案,我们能够有效地对敏感数据进行脱敏处理,从而保护用户隐私和数据安全,希望对大家有所帮助😊。
发表评论