DEV Community

Anh Trần Tuấn
Anh Trần Tuấn

Posted on • Originally published at tuanh.net on

Secrets to Masking Sensitive Data Before Sending to the Frontend in Java

1. Why Masking Sensitive Data is Essential

Masking data refers to transforming sensitive information into a partially or entirely obfuscated format to prevent unauthorized access or exposure. Before diving into the technical aspects, it's crucial to understand why this practice matters.

Protecting User Privacy

User privacy laws such as GDPR and CCPA enforce strict guidelines on how personal data should be handled. Masking data helps businesses comply with these regulations by ensuring only non-identifiable data is shared.

Mitigating Security Risks

Even if your backend is secure, exposing sensitive data in its raw form to the frontend increases the attack surface. Masking sensitive information significantly reduces the potential damage caused by data leaks.

2. Techniques for Masking Data in Java

Java provides robust libraries and tools to implement masking strategies effectively. Here, we’ll cover various approaches, from basic manual masking to leveraging libraries.

2.1 Basic Manual Masking

The simplest way to mask data is to manually replace specific characters with symbols such as *.

Code Example: Masking a Credit Card Number

public class DataMaskingUtil {

    public static String maskCreditCard(String creditCardNumber) {
        if (creditCardNumber == null || creditCardNumber.length() < 6) {
            throw new IllegalArgumentException("Invalid credit card number");
        }

        int prefixLength = 4;
        int suffixLength = 4;
        String prefix = creditCardNumber.substring(0, prefixLength);
        String suffix = creditCardNumber.substring(creditCardNumber.length() - suffixLength);
        String masked = "*".repeat(creditCardNumber.length() - prefixLength - suffixLength);

        return prefix + masked + suffix;
    }

    public static void main(String[] args) {
        String cardNumber = "1234567812345678";
        System.out.println(maskCreditCard(cardNumber)); // Output: 1234 ******** 5678
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • The prefix and suffix are retained for identification purposes.
  • The rest of the digits are replaced with *, ensuring sensitive parts remain hidden.

2.2 Using Regular Expressions for Flexible Masking

Regular expressions provide a powerful way to mask patterns in strings, such as email addresses or Social Security numbers.

Code Example: Masking an Email Address

public class EmailMaskingUtil {

    public static String maskEmail(String email) {
        if (email == null || !email.contains("@")) {
            throw new IllegalArgumentException("Invalid email address");
        }

        String[] parts = email.split("@");
        String localPart = parts[0];
        String domain = parts[1];

        String maskedLocalPart = localPart.charAt(0) + "*".repeat(Math.max(0, localPart.length() - 2)) + localPart.charAt(localPart.length() - 1);

        return maskedLocalPart + "@" + domain;
    }

    public static void main(String[] args) {
        String email = "john.doe@example.com";
        System.out.println(maskEmail(email)); // Output: j ******* e@example.com
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Only the first and last characters of the local part are exposed.
  • Regular expressions split the email into identifiable components for flexible manipulation.

2.3 Masking JSON Data Using Libraries

When handling structured data, like JSON, masking requires more sophisticated tools. Libraries such as Jackson can be extended to mask sensitive fields dynamically.

Code Example: Masking Fields in JSON

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

class User {
    @JsonProperty("name")
    private String name;

    @JsonProperty("creditCard")
    private String creditCard;

    public User(String name, String creditCard) {
        this.name = name;
        this.creditCard = creditCard;
    }

    public String getName() {
        return name;
    }

    public String getMaskedCreditCard() {
        return DataMaskingUtil.maskCreditCard(this.creditCard);
    }
}

public class JsonMaskingDemo {
    public static void main(String[] args) throws JsonProcessingException {
        User user = new User("John Doe", "1234567812345678");
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(user)); 
        // Output: {"name":"John Doe","creditCard":"1234 ******** 5678"}
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Sensitive fields such as credit card numbers are masked during serialization.
  • Custom masking logic is applied using utility functions.

3. Best Practices for Data Masking

Masking data effectively requires more than writing code. Best practices ensure robustness and compliance.

Mask at the Right Layer

Data should ideally be masked at the service layer before it reaches the API response. This ensures the backend itself doesn’t leak sensitive information.

Audit and Monitor Logs

Make sure your logging systems don’t inadvertently capture sensitive data before masking. Use log sanitizers to handle this.

4. Advanced Techniques: Leveraging Frameworks

Frameworks like Spring provide built-in mechanisms for masking data in specific scenarios, such as logging.

4.1 Masking Sensitive Data in Spring Logs

Spring Boot’s Logback allows you to customize log patterns and mask sensitive fields.

Configuration Example

<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %replace(%msg){'\d{16}', ' ****'}%n</pattern>
        </encoder>
    </appender>
    <root level="info">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>
Enter fullscreen mode Exit fullscreen mode

5. Conclusion

Masking sensitive data is a critical part of any secure application. By using manual techniques, regular expressions, or powerful libraries, Java developers can ensure sensitive information remains hidden from unauthorized eyes. Remember, this is just one layer of defense in a multi-layered security strategy.

Do you have questions or unique scenarios regarding masking data? Feel free to comment below—I’d be happy to discuss and provide further insights!

Read posts more at : Secrets to Masking Sensitive Data Before Sending to the Frontend in Java

Top comments (0)