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.
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
EnvironmentPostProcessorthat 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
EnableEncryptablePropertySourcesPostProcessorwith broader algorithm support.
See jasypt source: https://gitee.com/log4j/pig
Java Architecture Diary
Committed to sharing original, high‑quality technical articles; no fluff or promotional content.
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.