EnableEncryptableProperties – Jasypt
Spring EnableEncryptableProperties
with Jasypt shows an example how to avoid clear text password for database connection’s credentials in properties file. Jasypt means Java simplified encryption. Here I am going to use Spring Boot with Jasypt (Java simplified encryption). Here I am also going to use Spring Data JPA to perform the data layer activities with database.
If you put clear text password in properties file then everybody including people, who should not see password, would gain access to your database and may change database table values, table structure or even may delete data from database table without your consent. So it is always better to put the password in an encrypted format to avoid such unwanted issues.
Jasypt Spring Boot provides Encryption support for property sources in Spring Boot Applications.
There are three ways to integrate Jasypt in your spring boot project:
- Simply adding the starter jar jasypt-spring-boot-starter to your classpath if you are using
@SpringBootApplication
or@EnableAutoConfiguration
will enable encryptable properties across the entire Spring Environment. - Adding jasypt-spring-boot-starter to your classpath and adding
@EnableEncryptableProperties
to your main Configuration class to enable encryptable properties across the entire Spring Environment. - Adding jasypt-spring-boot-starter to your classpath and declaring individual encryptable property sources with
@EncrytablePropertySource
.
Prerequisites
Java 1.8+, Gradle 6.5.1 – 6.8.3, Maven 3.6.3/3.8.5, Spring Boot 2.3.1 – 2.4.4/2.7.5, Jasypt 3.0.3/3.0.4
Here I will show you an example by adding jasypt-spring-boot-starter to classpath and adding @EnableEncryptableProperties
to Configuration class to enable encryptable properties.
Project Setup
Create gradle or maven based project called spring-jasypt-enableencryptableproperties in your favorite IDE or tool.
Modify your build.gradle script with the following content in order to add required dependencies and configurations.
buildscript {
ext {
springBootVersion = '2.3.1.RELEASE' //to 2.4.4
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
plugins {
id 'java-library'
id 'org.springframework.boot' version "${springBootVersion}"
}
sourceCompatibility = 12
targetCompatibility = 12
repositories {
mavenCentral()
}
dependencies {
implementation "org.springframework.boot:spring-boot-starter:${springBootVersion}"
implementation("org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}")
implementation('com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.3')
runtime("mysql:mysql-connector-java:8.0.17") //to 8.0.22
//required for jdk 9 or above
runtimeOnly('javax.xml.bind:jaxb-api:2.4.0-b180830.0359')
}
For maven based project you can use the following pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.roytuts</groupId>
<artifactId>spring-jasypt-enableencryptableproperties</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>12</maven.compiler.source>
<maven.compiler.target>12</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4/2.7.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3/3.0.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--required only if jdk 9 or higher version is used -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Config File
Create application.properties file under classpath directory src/main/resources with the following content.
In this file I have basically put the MySQL database configurations. You need to change according to your database host, port, service name, username and password or you can use database of your choice.
Here you see I have added ENC()
method to let spring know that I am setting encrypted password and it needs to be decrypted while Spring tries to establish the connection with database. This is where the example shows how Spring EnableEncryptableProperties
with Jasypt (Java simplified encryption) works.
Now check I have added another line jasypt.encryptor.password=test
(you can have other values as per your choice) and it is required to decrypt your encrypted password. This value was used while I encrypted the database password and passed the encrypted password into ENC()
method.
Now while spring tries to connect to database, it first decrypts the encrypted password using jasypt.encryptor.password
(here the value is ‘test’) and connects to database. If you do not want to keep this jasypt.encryptor.password
in application.properties file then you can pass this as VM argument -Djasypt.encryptor.password=test
, while you are running the application.
If you want you can encrypt every key/value pair of the application.properties file but only the password field is sensitive so I have encrypted only password here.
By default the Jasypt uses PBEWITHMD5ANDDES algorithm for encrypting/decrypting value before version 3.0.0.
The default encryption/decryption algorithm has changed to PBEWITHHMACSHA512ANDAES_256 from version 3.0.0 of jasypt-spring-boot. So you have to add another line in application.properties file:
jasypt.encryptor.iv-generator-classname=org.jasypt.iv.NoIvGenerator
The complete application.properties file is given below:
spring.datasource.url=jdbc:mysql://localhost/roytuts
spring.datasource.username=root
spring.datasource.password=ENC(ZbkVUeL0Z7/ZbiGV9dh6mA==)
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
jasypt.encryptor.algorithm=PBEWithMD5AndDES
jasypt.encryptor.password=test
jasypt.encryptor.iv-generator-classname=org.jasypt.iv.NoIvGenerator
#disable schema generation from Hibernate
spring.jpa.hibernate.ddl-auto=none
Entity Class
Suppose I have a user table that stores all users information and I have the following entity class with the below attributes and corresponding columns in the user table.
I have removed the getters and setters and you can always generate from option in Eclipse.
@Entity
@Table(name = "user")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "email")
private String email;
@Column(name = "phone")
private String phone;
@Column(name = "address")
private String address;
//getters and setters
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", email=" + email + ", phone=" + phone + ", address=" + address
+ "]";
}
}
Config Class
I will use annotation based configurations, so I need following configuration class in order to use Spring EnableEncryptableProperties
annotation along with DataSource configuration for database.
I am using Spring Data JPA to perform query on database, so I have defined spring beans EntityManagerFactory
and DataSource.
I have configured JPA Repositories using annotation EnableJpaRepositories
.
I have also let spring know where entity class is kept using factory.setPackagesToScan("com.roytuts.spring.jasypt.enableencryptableproperties.model")
.
@Configuration
@EnableEncryptableProperties
@EnableJpaRepositories(basePackages = "com.roytuts.spring.jasypt.enableencryptableproperties.repository")
public class Config {
@Autowired
private Environment environment;
@Bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(environment.getRequiredProperty("spring.datasource.driverClassName"));
ds.setUrl(environment.getRequiredProperty("spring.datasource.url"));
ds.setUsername(environment.getRequiredProperty("spring.datasource.username"));
ds.setPassword(environment.getRequiredProperty("spring.datasource.password"));
return ds;
}
@Bean
public EntityManagerFactory entityManagerFactory(DataSource dataSource) {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.MYSQL);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.roytuts.spring.jasypt.enableencryptableproperties.model");
factory.setDataSource(dataSource);
factory.afterPropertiesSet();
return factory.getObject();
}
}
JPA Repository
Create below JPA repository interface that extends Spring’s JpaRepository
interface to get advantages of the Spring’s built-in functionalities.
public interface UserJpaRepository extends JpaRepository<User, Integer> {
}
Service Class
This service class is responsible for fetching data from JPA repository and performing any business logic if required and communicates with controller.
The below service class gets all users from the data layer and process any business logic and finally sends to controller layer.
@Service
public class UserService {
@Autowired
private UserJpaRepository repository;
public List<User> getUserList() {
return repository.findAll();
}
}
Spring Boot Main Class
Create below main class to startup the Spring Boot application example Spring EnableEncryptableProperties
with Jasypt (Java simplified encryption).
You need to scan the base packages to let spring know where you have put all of your controller, service, repository, entity, configuration classes.
@SpringBootApplication
public class JasyptEnableEncryptablePropertiesApp implements CommandLineRunner {
@Autowired
private UserService service;
public static void main(String[] args) {
SpringApplication.run(JasyptEnableEncryptablePropertiesApp.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println(service.getUserList());
}
}
Testing Jasypt
Running the above main class will give you the following output:
[User [id=1, name=Soumitra Roy, email=sroy@gmail.com, phone=2147483647, address=Earth], User [id=2, name=Rahul Kumar, email=rahul@gmail.com, phone=34256780, address=Mars]]
That’s all. Hope you got idea how to use Jasypt (Java simplified encryption) by going through example Spring EnableEncryptableProperties with Jasypt (Java simplified encryption).