Encrypting Plaintext Passwords in SpringBoot Configuration Using Jasypt
This article explains how to protect sensitive database credentials in SpringBoot applications by encrypting passwords in configuration files, leveraging Jasypt and a custom BeanFactoryPostProcessor to transparently decrypt values at runtime.
When sensitive information such as database usernames and passwords is stored directly in yaml or properties files, the risk of leakage increases; encrypting these values and decrypting them only when needed mitigates that risk.
The article first shows a plain configuration snippet:
spring:
datasource:
url: jdbc:mysql://xx.xx.xx.xx:3306/database
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: "123456"and then the encrypted version using Jasypt:
spring:
datasource:
url: jdbc:mysql://xx.xx.xx.xx:3306/database
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: "AES(DzANBAhBWXxZqAOsagIBCoaw8FV4gYRbid7G70UEM24=)"To intercept configuration values, a custom BeanFactoryPostProcessor is implemented. The processor obtains all PropertySource objects from the ConfigurableEnvironment , filters out those that should not be wrapped, and replaces them with a proxy that performs decryption when a property is accessed.
public class PropertySourcePostProcessor implements BeanFactoryPostProcessor {
private ConfigurableEnvironment environment;
public PropertySourcePostProcessor(ConfigurableEnvironment environment) {
this.environment = environment;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
MutablePropertySources propertySources = this.environment.getPropertySources();
propertySources.stream()
.filter(s -> !noWrapPropertySource(s))
.map(s -> new EncryPropertySource(s))
.collect(Collectors.toList())
.forEach(wrap -> propertySources.replace(wrap.getName(), wrap));
}
private boolean noWrapPropertySource(PropertySource propertySource) {
return propertySource instanceof EncryPropertySource ||
StringUtils.equalsAny(propertySource.getClass().getName(),
"org.springframework.core.env.PropertySource$StubPropertySource",
"org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource");
}
}The Jasypt starter is added as a Maven dependency:
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>Configuration for Jasypt specifies the encryption password, prefix, and suffix (default prefix ENC( and suffix ) ), for example:
jasypt:
encryptor:
password: "mySecretKey"
property:
prefix: "ENC("
suffix: ")"If the built‑in encryptor does not meet project needs, a custom StringEncryptor bean can be defined:
@Bean("jasyptStringEncryptor")
public StringEncryptor jasyptStringEncryptor() {
return new StringEncryptor() {
@Override
public String encrypt(String s) { /* TODO */ return null; }
@Override
public String decrypt(String s) { /* TODO */ return null; }
};
}To generate encrypted values, the StringEncryptor can be autowired and used once during the project lifecycle:
@Component
public class StringEncryptorUtil {
@Autowired
private StringEncryptor encryptor;
public void encrypt() {
String result = encryptor.encrypt("123456");
System.out.println(result);
}
}By integrating this approach, sensitive passwords remain encrypted in source files while the application can transparently decrypt them at runtime, enhancing configuration security.
IT Xianyu
We share common IT technologies (Java, Web, SQL, etc.) and practical applications of emerging software development techniques. New articles are posted daily. Follow IT Xianyu to stay ahead in tech. The IT Xianyu series is being regularly updated.
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.