Information Security 8 min read

Secure API Responses with Data Masking, Encryption, and Jackson Annotations

This article explains practical methods to protect sensitive API data in Spring Boot applications, covering encryption, masking, access control, logging, HTTPS, and database security, and demonstrates three implementation approaches: SQL‑level masking, field‑level encryption, and custom Jackson serialization using annotations and a contextual serializer.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Secure API Responses with Data Masking, Encryption, and Jackson Annotations

Environment: SpringBoot2.6.12

API interface data masking is an important method for protecting sensitive data. It replaces sensitive information with meaningless or disguised data during transmission and storage to prevent unauthorized access and leakage.

Data Encryption : Use encryption algorithms (e.g., AES, RSA) to encrypt sensitive data so that intercepted data cannot be decrypted.

Data Masking : Replace sensitive data with meaningless or disguised values, such as random phone numbers or fake names.

Access Control : Apply authentication and authorization (e.g., JWT, OAuth) to restrict API access to verified users.

Logging : Record detailed logs of API access and usage for rapid incident response.

Data Transmission Security : Use HTTPS to secure data in transit.

Data Storage Security : Store sensitive data in encrypted databases and enforce ACLs.

In projects, some API fields should not be transmitted in plain text. The following three methods can be used:

Database‑Level Processing

Processing data in SQL queries is generally inefficient and not recommended. Example:

<code>SELECT CONCAT(LEFT(idNo, 6), '********', RIGHT(idNo, 4)) AS idNo
FROM users WHERE id = 7;</code>

Query result:

Data Encryption Processing

This approach encrypts the entire field using symmetric encryption or hash algorithms during write or read operations. Example:

<code>import java.sql.*;

public class JdbcSensitiveDataProcess {
    public static void main(String[] args) {
        try {
            // Connect to database
            Connection conn = DataSourceUtils.getConnection();
            // Create Statement
            Statement stmt = conn.createStatement();
            // Execute query
            ResultSet rs = stmt.executeQuery("SELECT id, name, encrypted_data FROM t_xxx");
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String encryptedData = rs.getString("encrypted_data");
                // Decrypt the data
                String decryptedData = decryptData(encryptedData);
                System.out.println("ID: " + id + ", Name: " + name + ", Decrypted Data: " + decryptedData);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Close resources
        }
    }

    // Example decryption method (implementation depends on the algorithm used)
    private static String decryptData(String encryptedData) {
        // Decryption logic...
        return encryptedData; // placeholder
    }
}
</code>

JSON Serialization Processing

During JSON serialization, sensitive fields can be masked or encrypted. The following demonstrates a custom Jackson annotation approach.

JSON Serialization Masking

Using Jackson, define a custom annotation to handle sensitive fields during object serialization.

<code>@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerializer.class)
public @interface Sensitive {
    /** Regular expression */
    String pattern() default "";
    /** Which regex group to replace with mask */
    int group() default 0;
    /** Mask character */
    String mask() default "*";
    interface Pattern {
        /** ID card */
        String ID = "(\\w{5})(\\w+)(\\w{3})";
        /** Phone */
        String PHONE = "(\\w){3}(\\w+)(\\w{2})";
        /** Key */
        String KEY = "(\\w+)";
    }
}
</code>

The annotation provides pattern, group, and mask attributes for flexible masking.

<code>public class SensitiveSerializer extends JsonSerializer<String> implements ContextualSerializer {
    private Sensitive sensitive;

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        String val = value;
        if (sensitive != null) {
            String pattern = sensitive.pattern();
            int groupIndex = sensitive.group();
            String mask = sensitive.mask();
            if (pattern.length() > 0) {
                Pattern pa = Pattern.compile(pattern);
                Matcher matcher = pa.matcher(value);
                if (matcher.matches()) {
                    String group = matcher.group(groupIndex);
                    if (mask.length() > 0 && group.length() > 0) {
                        val = val.replace(group, String.join("", Collections.nCopies(group.length(), mask)));
                    }
                }
            }
        }
        gen.writeObject(val);
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        sensitive = property.getAnnotation(Sensitive.class);
        return this;
    }
}
</code>

This serializer reads the @Sensitive annotation on a field and applies the defined masking logic.

<code>public class Users {
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+10")
    private Date birthday;
    private Integer age;
    private String name;
    // Apply the custom annotation to the field that needs masking
    @Sensitive(pattern = Sensitive.Pattern.ID)
    private String idNo;
}
</code>

Result:

idNo is masked according to the specified rule.

JavaSpring BootJacksonAPI securitydata masking
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.