Implementing Data Masking in SQL, Java, and MyBatis‑Mate Sensitive Jackson
This article demonstrates how to mask sensitive data such as phone numbers, ID cards, and personal information using SQL string functions, a Java library (sensitive‑plus), and the MyBatis‑Mate Sensitive Jackson plugin, providing complete code examples, configuration files, and test results for backend developers.
Hello, I am a senior architect sharing three practical data‑masking solutions.
1. SQL Data Masking Implementation
Using MySQL string functions CONCAT, LEFT, and RIGHT to mask phone numbers and ID cards.
-- Phone number masking
SELECT mobilePhone AS original_phone,
CONCAT(LEFT(mobilePhone,3), '********') AS masked_phone
FROM t_s_user;
-- ID card masking
SELECT idcard AS original_id,
CONCAT(LEFT(idcard,3), '****', RIGHT(idcard,4)) AS masked_id
FROM t_s_user;2. Java Data Masking Implementation
Reference the open‑source sensitive‑plus library, which supports address, bank card, Chinese name, landline, ID card, mobile number, and password masking via regular expressions or length‑based strategies.
3. mybatis‑mate‑sensitive‑jackson
A MyBatis‑Mate extension that applies masking strategies defined in SensitiveType . The plugin is free for testing; production use requires a license.
package mybatis.mate.strategy;
public interface SensitiveType {
String chineseName = "chineseName";
String idCard = "idCard";
String phone = "phone";
String mobile = "mobile";
String address = "address";
String email = "email";
String bankCard = "bankCard";
String password = "password";
String carNumber = "carNumber";
}Demo project structure includes:
pom.xml with MySQL connector dependency
application.yml configuring the datasource and MyBatis‑Mate license
SpringBoot entry class SensitiveJacksonApplication
Configuration class injecting a custom strategy
Entity User with @FieldSensitive annotations
REST controller exposing /info , /map , and /list endpoints
Mapper interface extending BaseMapper<User>
# pom.xml snippet
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
<parent>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-mate-examples</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mybatis-mate-sensitive-jackson</artifactId>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project> # application.yml snippet
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_mate?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 123456
mybatis-mate:
cert:
grant: thisIsTestLicense
license: ... (license string) // SensitiveJacksonApplication.java
package mybatis.mate.sensitive.jackson;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SensitiveJacksonApplication {
public static void main(String[] args) {
SpringApplication.run(SensitiveJacksonApplication.class, args);
}
} // SensitiveStrategyConfig.java
package mybatis.mate.sensitive.jackson.config;
import mybatis.mate.databind.ISensitiveStrategy;
import mybatis.mate.strategy.SensitiveStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SensitiveStrategyConfig {
@Bean
public ISensitiveStrategy sensitiveStrategy() {
return new SensitiveStrategy().addStrategy("testStrategy", t -> t + "***test***");
}
} // User entity
package mybatis.mate.sensitive.jackson.entity;
import lombok.Getter;
import lombok.Setter;
import mybatis.mate.annotation.FieldSensitive;
import mybatis.mate.strategy.SensitiveType;
@Getter @Setter
public class User {
private Long id;
@FieldSensitive("testStrategy")
private String username;
@FieldSensitive(SensitiveType.mobile)
private String mobile;
@FieldSensitive(SensitiveType.email)
private String email;
} // UserController.java (excerpt)
@GetMapping("/info")
public User info() {
return userMapper.selectById(1L);
}
@GetMapping("/list")
public List
list(HttpServletRequest request) {
if ("1".equals(request.getParameter("skip"))) {
RequestDataTransfer.skipSensitive();
}
return userMapper.selectList(null);
}Test requests:
# GET http://localhost:8080/list
[ {"id":1,"username":"Jone***test***","mobile":"153******81","email":"t****@baomidou.com"}, ... ]
# GET http://localhost:8080/list?skip=1
[ {"id":1,"username":"Jone","mobile":"15315388881","email":"[email protected]"}, ... ]The article provides a complete, ready‑to‑run example for developers who need to protect personal data in backend systems.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.