浅谈Java后端用户信息接口脱敏
在开发中,接口往往会返回用户的敏感信息,比如手机号、身份证号、邮箱等。为了保护用户隐私、降低安全风险、并满足法律合规要求,我们需要对这些数据进行脱敏处理。
本文基于 Spring Boot 和 Jackson 提供一种灵活的注解式脱敏方案,并结合 Hutool 工具类 DesensitizedUtil
做扩展与优化。
什么是接口数据脱敏?
接口数据脱敏,是指在对外提供 API 时,对返回数据中的敏感信息进行隐藏或模糊处理,常见包括:
- 手机号
13812345678
➜ 138****5678
- 身份证号
123456789012345678
➜ 1234******5678
- 邮箱
example@example.com
➜ exa****@example.com
为什么要做脱敏?
- ✅ 保护用户隐私:避免敏感信息泄露
- ✅ 满足合规要求:符合《个人信息保护法》等法规
- ✅ 降低安全风险:防止数据被非法利用
项目环境
- IDE:IntelliJ IDEA
- JDK:1.8+
- Spring Boot:2.5.4
Maven 依赖:
1 2 3 4 5 6 7 8 9 10
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> </dependencies>
|
🛠 实现步骤
1. 定义注解 @Sensitive
1 2 3 4 5
| @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Sensitive { SensitiveType type(); }
|
2. 定义脱敏类型枚举
1 2 3 4 5
| public enum SensitiveType { MOBILE, ID_CARD, EMAIL }
|
3. 自定义序列化器 SensitiveSerializer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class SensitiveSerializer extends JsonSerializer<String> { private final SensitiveType type;
public SensitiveSerializer(SensitiveType type) { this.type = type; }
@Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { switch (type) { case MOBILE: gen.writeString(value.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")); break; case ID_CARD: gen.writeString(value.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1******$2")); break; case EMAIL: gen.writeString(value.replaceAll("(^[^@]{3})[^@]*(@.*$)", "$1****$2")); break; default: gen.writeString(value); } } }
|
实战测试
User 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class User { private String name;
@Sensitive(type = SensitiveType.MOBILE) @JsonSerialize(using = SensitiveSerializer.class) private String mobile;
@Sensitive(type = SensitiveType.ID_CARD) @JsonSerialize(using = SensitiveSerializer.class) private String idCard;
@Sensitive(type = SensitiveType.EMAIL) @JsonSerialize(using = SensitiveSerializer.class) private String email;
}
|
Controller 实战
1 2 3 4 5 6 7 8 9 10 11 12
| @RestController public class UserController { @GetMapping("/user") public User getUser() { User user = new User(); user.setName("张三"); user.setMobile("13812345678"); user.setIdCard("123456789012345678"); user.setEmail("example@example.com"); return user; } }
|
接口输出结果
1 2 3 4 5 6
| { "name": "张三", "mobile": "138****5678", "idCard": "1234******5678", "email": "exa****@example.com" }
|
Hutool 是一个非常实用的 Java 工具类库,其中 cn.hutool.core.util.DesensitizedUtil
提供了多种类型的脱敏方法,支持手机号、身份证号、邮箱、地址、银行卡号等。
示例用法
1 2 3 4 5 6 7 8
| DesensitizedUtil.mobilePhone("13812345678")
DesensitizedUtil.idCardNum("123456789012345678", 4, 4)
DesensitizedUtil.email("example@example.com")
|
结合使用
可以在 SensitiveSerializer
中调用 Hutool 提供的方法,替代正则逻辑,代码更简洁、可读性更高:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { String desensitized; switch (type) { case MOBILE: desensitized = DesensitizedUtil.mobilePhone(value); break; case ID_CARD: desensitized = DesensitizedUtil.idCardNum(value, 4, 4); break; case EMAIL: desensitized = DesensitizedUtil.email(value); break; default: desensitized = value; } gen.writeString(desensitized); }
|
💡 Tips:生产环境可结合 AOP、全局 ObjectMapper 或 ResponseBodyAdvice 进一步封装为全局脱敏处理策略。