Shielding sensitive information: PII masking with Spring Boot

Opcito Technologies
2 min readMar 5, 2024

In an era dominated by data-driven applications, safeguarding sensitive information has become paramount. Personally Identifiable Information (PII) is particularly vulnerable and requires robust protection to adhere to privacy regulations and ensure user trust. This PII data can be Telephone Numbers, Email, Password, etc.

This blog explores how to implement PII data masking in Spring Boot applications, addressing the purpose, problems, and advantages of this approach.

Problems with PII exposure

  • Regulatory compliance: Stringent data protection regulations, such as GDPR and HIPAA, require the secure handling of Personally Identifiable Information (PII). Failure to comply may lead to serious legal consequences.
  • Security threats: The exposure of unmasked PII heightens the vulnerability to identity theft, fraud, and various cybercrimes. Security breaches pose a substantial threat, possibly inflicting irreparable damage to an organization’s reputation.
  • User trust: Users trust organizations to safeguard their sensitive information. Any lapse in PII handling jeopardizes this trust, potentially leading users to abandon services.

Why use Spring Boot for PII data masking

Spring Boot offers a flexible approach to the implementation of PII data masking. Its adaptability allows the creation of customized data masking logic that is finely tuned to specific types of personally identifiable information (PII) and the application’s unique requirements. Additionally, Spring Boot ensures a seamless integration experience by harmoniously blending with various technologies. This smooth integration enables the implementation of PII data masking without causing significant disruptions to existing systems, contributing to an efficient and streamlined process.

Practical implementation:

Following is a domain object, which is a User. This User information can come from a Database, file, or another REST API endpoint.

@Data 
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class User {
private int id;
private String name;
@MaskData
private String ssn;
@MaskData
private String phoneNumber;
private int age;
private String username;
@MaskData
private String password;
private List<AccountDetails> accountDetails;
}
@Data 
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AccountDetails {
private String accountHolderName;
@MaskData
private String accountNumber;
private String accountType;
}

And we have our own REST API endpoint to support this UserController.

@RestController 
@RequestMapping("/users")
public class UserController {

@Autowired
private UserService userService;

@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}

@GetMapping("/{id}")
public User getUser(@PathVariable int id) {
return userService.getUser(id);
}

}

Steps to create a user service component responsible for retrieving data from memory, database, or any other source.

@Service 
public class UserService {

public List<User> getAllUsers() {

User user1 = new User(3235, "john", "6474729899", "1234567890", 30, "johncn", "john123",
List.of(new AccountDetails("John Chen", "365027332671", "SAVING")
, new AccountDetails("John Chen", "365027332671", "CURRENT")));

User user2 = new User(9546, "Nancy", "4623642828", "5439854674", 41, "nancygb", "nancy619",
List.of(new AccountDetails("Nancy Greenberg", "8272389200", "SAVING")));

return Stream.of(user1, user2).collect(Collectors.toList());
}

public User getUser(int id) {
return getAllUsers().stream().filter(user -> user.getId() == id)
.findFirst()
.orElseThrow(() -> new RuntimeException("user not found"));
}
}

Steps to create a custom data serializer by extending JSON Serializer
(read more..)

--

--

Opcito Technologies

Product engineering experts specializing in DevOps, Containers, Cloud, Automation, Blockchain, Test Engineering, & Open Source Tech