基于Jackson实现API接口数据脱敏的示例详解
作者:skywsp
用户的一些敏感数据,例如手机号、邮箱、身份证等信息,在数据库以明文存储,但在接口返回数据给浏览器(或三方客户端)时,希望对这些敏感数据进行脱敏,所以本文就给大家介绍以恶如何利用Jackson实现API接口数据脱敏,需要的朋友可以参考下
一、背景
用户的一些敏感数据,例如手机号、邮箱、身份证等信息,在数据库以明文存储(加密存储见《基于Mybatis-Plus拦截器实现MySQL数据加解密》), 但在接口返回数据给浏览器(或三方客户端)时,希望对这些敏感数据进行脱敏。 同时在浏览器提交数据更新到后端接口时,后端接口需要判断敏感数据是否已脱敏,如果已脱敏则需要直接丢弃。
二、Jackson介绍
Jackson是SpringBoot默认的Json序列化和反序列化库,点击这里查看Jackson注解官方文档.
本文通过使用Jackson的@JsonSerialize注解实现序列化时脱敏操作,通过使用Jackson的@JsonDeserialize注解实现反序列化时脱敏数据检测并丢弃操作。
三、使用方法
该脱敏拦截器功能在wutong-base-api包(公司内部包)已经实现,如果您的项目已经依赖了base-api,就可以直接使用。
另外,在码云上有Demo案例,见: spring-jackson
基于wutong-base-api包的使用步骤如下。
1、添加wutong-base-api依赖
<dependency> <groupId>com.talkweb</groupId> <artifactId>wutong-base-api</artifactId> <version>请使用最新版本</version> </dependency>
2、在yaml配置开关,启用加解密
spring: jackson: sensitive: # 序列化时是否对手机号进行脱敏,反序列化时是否过滤脱敏数据 mobile: true # 序列化时是否对邮箱进行脱敏,反序列化时是否过滤脱敏数据 email: true # 序列化时是否对身份证号进行脱敏,反序列化时是否过滤脱敏数据 identity: true
3、定义VO类,使用Jackson注解实现数据脱敏
API接口出参(Rsp),敏感数据序列化时脱敏
public class UserRspVO { private Long id; private String name; @JsonSerialize(using = CustomerJackSon.MobileSerialize.class) private String mobile; @JsonSerialize(using = CustomerJackSon.EmailSerialize.class) private String email; @JsonSerialize(using = CustomerJackSon.IdentitySerialize.class) private String identity; }
API接口入参(Req),过滤已脱敏的数据,直接丢弃
public class UserReqVO { private Long id; private String name; @JsonDeserialize(using = CustomerJackSon.MobileDeSerialize.class) private String mobile; @JsonDeserialize(using = CustomerJackSon.EmailDeSerialize.class) private String email; @JsonDeserialize(using = CustomerJackSon.IdentityDeSerialize.class) private String identity; }
定义Controller接口
@RestController @RequestMapping("/user") public class UserController { @GetMapping public UserRspVO get() { UserRspVO rsp = new UserRspVO(); rsp.setId(1L); rsp.setName("张三"); rsp.setMobile("18866661234"); rsp.setEmail("zhangsan@qq.com"); rsp.setIdentity("434113199901015566"); return rsp; } @PutMapping public UserRspVO put(@RequestBody UserReqVO req) { System.out.println(req); UserRspVO rsp = new UserRspVO(); BeanUtils.copyProperties(req, rsp); return rsp; } }
接口请求示例:
GET http://localhost:8080/user 入参: 无 出参: { "id": "1", "name": "张三", "mobile": "188****1234", // 配置了mobile=true "email": "zhangsan@qq.com", // 配置了email=false "identity": "434113199901015566" // 未配置identity,默认为false }
PUT http://127.0.0.1:8080/user 入参: { "id": "12124", "name": "张三", "mobile": "188****1234", "email": "zh****@qq.com", "identity": "434***********5566" } Controller反序列化后接收到的数据: { "id": "12124", "name": "张三", "mobile": null, // 配置了mobile=true "email": "zh****@qq.com", // 配置了email=false "identity": "434***********5566" // 未配置identity,默认为false }
四、实现原理
1、SpringBoot定义变量实现脱敏开关
读取yaml配置
@ConfigurationProperties(prefix = "spring.jackson.sensitive") public class JacksonProperties { private Boolean mobile; private Boolean email; private Boolean identity; }
变量注入到JacksonConfig
@Configuration @EnableConfigurationProperties(JacksonProperties.class) public class JacksonConfig { @Bean public ObjectMapper objectMapper(JacksonProperties props) { ObjectMapper mapper = new ObjectMapper(); ContextAttributes attrs = ContextAttributes.getEmpty() .withSharedAttribute("mobile", props.getMobile()) .withSharedAttribute("email", props.getEmail()) .withSharedAttribute("identity", props.getIdentity()); mapper.setDefaultAttributes(attrs); return mapper; } }
2、实现序列化、反序列化逻辑
public class CustomerJackSon { /** * 手机号脱敏序列化 */ public static class MobileSerialize extends JsonSerializer<String> { @Override public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { if (null == value || value.length() != 11) { jsonGenerator.writeString(value); return; } Boolean mobile = (Boolean) serializerProvider.getAttribute("mobile"); if (null == mobile || !mobile) { jsonGenerator.writeString(value); return; } jsonGenerator.writeString(value.substring(0, 3) + "****" + value.substring(7)); } } /** * 手机号脱敏数据检测并丢弃 */ public static class MobileDeSerialize extends JsonDeserializer<String> { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { String value = p.getText(); if (null == value || value.length() != 11) { return value; } Boolean mobile = (Boolean) ctxt.getAttribute("mobile"); if (null == mobile || !mobile) { return value; } if (value.contains("*")) { return null; } return value; } } /** * 邮箱脱敏序列化 */ public static class EmailSerialize extends JsonSerializer<String> { @Override public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { if (null == value || value.length() < 5) { jsonGenerator.writeString(value); return; } String[] split = value.split("@"); if (split.length != 2 || split[0].length() < 2 || split[1].length() < 2) { jsonGenerator.writeString(value); return; } Boolean email = (Boolean) serializerProvider.getAttribute("email"); if (null == email || !email) { jsonGenerator.writeString(value); return; } jsonGenerator.writeString(split[0].substring(0, 2) + "****@" + split[1]); } } /** * 邮箱脱敏数据检测并丢弃 */ public static class EmailDeSerialize extends JsonDeserializer<String> { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { String value = p.getText(); if (null == value || value.length() < 5) { return value; } Boolean email = (Boolean) ctxt.getAttribute("email"); if (null == email || !email) { return value; } if (value.contains("*")) { return null; } return value; } } /** * 身份证脱敏序列化 */ public static class IdentitySerialize extends JsonSerializer<String> { @Override public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { if (null == value || value.length() != 18) { jsonGenerator.writeString(value); return; } Boolean identity = (Boolean) serializerProvider.getAttribute("identity"); if (null == identity || !identity) { jsonGenerator.writeString(value); return; } jsonGenerator.writeString(value.substring(0, 3) + "***********" + value.substring(14)); } } /** * 身份证脱敏数据检测并丢弃 */ public static class IdentityDeSerialize extends JsonDeserializer<String> { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { String value = p.getText(); if (null == value || value.length() != 18) { return value; } Boolean identity = (Boolean) ctxt.getAttribute("identity"); if (null == identity || !identity) { return value; } if (value.contains("*")) { return null; } return value; } } }
以上就是基于Jackson实现API接口数据脱敏的示例详解的详细内容,更多关于Jackson API接口数据脱敏的资料请关注脚本之家其它相关文章!