Backend Development 6 min read

How MyBatis-Plus Secures Configurations with a Custom EnvironmentPostProcessor

This article explains how MyBatis-Plus adds data-security protection to Spring Boot applications by encrypting datasource and property file values, details the custom EnvironmentPostProcessor implementation, loading mechanisms, and offers extension ideas and alternatives such as jasypt-spring-boot-starter.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
How MyBatis-Plus Secures Configurations with a Custom EnvironmentPostProcessor

Background

Continuing from the previous article “Missing Population Returns, MyBatis-Plus 3.3.2 Released”, MyBatis-Plus introduces a practical “Data Security Protection” feature that can encrypt data source configurations as well as sensitive information in Spring Boot global yml/properties files, helping to mitigate leakage caused by developer turnover.

<code>// Data source sensitive information encryption
spring:
  datasource:
    url: mpw:qRhvCwF4GOqjessEB3G+a5okP+uXXr96wcucn2Pev6BfaoEMZ1gVpPPhdDmjQqoM
    password: mpw:Hzy5iliJbwDHhjLs1L0j6w==
    username: mpw:Xb+EgsyuYRXw7U7sBJjBpA==
</code>
<code>// Redis password encryption
spring:
  redis:
    password: mpw:Hzy5iliJbwDHhjLs1L0j6w==
</code>

Implementation Principle

Spring Boot documentation (section 4.2.6) states that it does not provide built‑in support for encrypted property values, but offers an extension point

EnvironmentPostProcessor

that allows manipulation of environment properties before the application starts.

MyBatis‑Plus Implementation

<code>public class SafetyEncryptProcessor implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        // Get key from command line
        String mpwKey = null;

        // Iterate all property sources
        for (PropertySource<?> ps : environment.getPropertySources()) {
            if (ps instanceof SimpleCommandLinePropertySource) {
                SimpleCommandLinePropertySource source = (SimpleCommandLinePropertySource) ps;
                mpwKey = source.getProperty("mpw.key");
                break;
            }
        }

        // Decrypt encrypted values and put them into a new map
        HashMap<String, Object> map = new HashMap<>();
        for (PropertySource<?> ps : environment.getPropertySources()) {
            if (ps instanceof OriginTrackedMapPropertySource) {
                OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) ps;
                for (String name : source.getPropertyNames()) {
                    Object value = source.getProperty(name);
                    if (value instanceof String) {
                        String str = (String) value;
                        if (str.startsWith("mpw:")) {
                            map.put(name, AES.decrypt(str.substring(4), mpwKey));
                        }
                    }
                }
            }
        }

        // Add decrypted values as highest‑priority property source
        if (!map.isEmpty()) {
            environment.getPropertySources().addFirst(new MapPropertySource("custom-encrypt", map));
        }
    }
}
</code>

How to Load

Configure SPI in

resources/META-INF/spring.factories

:

<code>org.springframework.boot.env.EnvironmentPostProcessor=\
  com.baomidou.mybatisplus.autoconfigure.SafetyEncryptProcessor
</code>

Extensions

MyBatis‑Plus reads the key from startup parameters by default; you can customize it for more secure storage.

Read from environment variable:

<code>System.getProperty("mpw.key")
</code>

Remote password service (example inspired by Druid ConfigFilter):

<code>// Example method to load configuration from various locations
public Properties loadConfig(String filePath) {
    Properties properties = new Properties();
    InputStream inStream = null;
    try {
        boolean xml = false;
        if (filePath.startsWith("file://")) {
            filePath = filePath.substring("file://".length());
            inStream = getFileAsStream(filePath);
            xml = filePath.endsWith(".xml");
        } else if (filePath.startsWith("http://") || filePath.startsWith("https://")) {
            URL url = new URL(filePath);
            inStream = url.openStream();
            xml = url.getPath().endsWith(".xml");
        } else if (filePath.startsWith("classpath:")) {
            String resourcePath = filePath.substring("classpath:".length());
            inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath);
            xml = resourcePath.endsWith(".xml");
        } else {
            inStream = getFileAsStream(filePath);
            xml = filePath.endsWith(".xml");
        }

        if (inStream == null) {
            LOG.error("load config file error, file : " + filePath);
            return null;
        }

        if (xml) {
            properties.loadFromXML(inStream);
        } else {
            properties.load(inStream);
        }
        return properties;
    } catch (Exception ex) {
        LOG.error("load config file error, file : " + filePath, ex);
        return null;
    } finally {
        JdbcUtils.close(inStream);
    }
}
</code>

Summary

Configuration file encryption/decryption is achieved by a custom

EnvironmentPostProcessor

.

If you are not using the latest MyBatis‑Plus version, you can implement a similar processor yourself, though the jasypt‑spring‑boot‑starter is recommended for more mature encryption options.

jasypt‑spring‑boot‑starter implements an

EnableEncryptablePropertySourcesPostProcessor

with broader algorithm support.

See jasypt source: https://gitee.com/log4j/pig

JavaSpring BootMyBatis-PlusConfiguration EncryptionEnvironmentPostProcessor
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

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.