Securing Database Credentials – Building a Blog
Previously in Building a Blog: Getting Started with MongoDB
With our database set up, it is now time to make a MongoDB connection with Spring Boot. That connects the database to our backend system, making us ready to start implementing our operations. However, I don’t want my database credentials to be all over GitHub. Therefore, in this post, I will be securing my database credentials.
I already had my Spring Boot project, but in case you don’t, go to https://start.spring.io/. Here, you can easily configure your start project with Spring Boot. For my project, I have selected the following dependencies:
- Spring Boot DevTools
- Spring Web
- Spring Security (I want to use JWT tokens later on in the project)
- Spring Data MongoDB
Let the website generate a project for you, unzip it and you should start with a blank Spring Boot project.
Securing Database Credentials
The first thing I want to do, is securing my database credentials. One of the places to put these, is in the application.properties file. However, this file gets uploaded to GitHub, which would mean that the database credentials would be visible to everyone. And, lets be honest, I don’t want that and you probably don’t want that either. So, it is time to implement a solution that would solve this.
Creating the Properties File
Java does have a sweet feature where you can tap into the system properties. In this case, I want to use the method System.getProperty("user.home")
. This method allows me to go to the home drive without hard-coding it. On Windows, the user.home
directory is usually located at C:\Users\<your username>\
. On Linux, it is the home directory. Using this method, we can make the software cross platform as well. I have created a subdirectory that will contain files for my project.
So, in this subdirectory, I created my properties file: rosafiore.properties
. In this file, I have set the username and password I’m using for my database connection. It looks somewhat like this:
username=<username>
password=<password>
Note that I am not using any accolades for the strings I use to define my username and password. Now, it is time to get back to the project in IntelliJ (or any other Java IDE you prefer). I have created the following file structure for my project:
Reading the Property File on StartUp
The first class I’m going to take a look at is the Config class. I use this class to load the properties from my property file with the following bit of code:
@Component
@ConfigurationProperties(prefix = "config")
@Validated
public class Config {
public static String USERNAME;
public static String PASSWORD;
private static final String PROPERTIES_LOCATION = System.getProperty("user.home") +
"/RosaFiore/rosafiore.properties";
public static void getConfig() {
Properties properties = new Properties();
try {
properties.load(new FileInputStream(PROPERTIES_LOCATION));
USERNAME = properties.getProperty("username");
PASSWORD = properties.getProperty("password");
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
We can now load the properties from our properties file! However, we need this to be done on startup of the application. So, we need to find a way to tap into the Spring Boot startup process and run this Config class. For this, we need to make some changes in the class where the main method resides.
In the class with our main method, I’m going to add an inner static class. This inner class allows us to use the getConfig()
from our Config class. We can achieve that by creating a class that implements an ApplicationListener. To be more specific, a listener that triggers on the ApplicationEnvironmentPreparedEvent
. By overriding onApplicationEvent()
, we can use Config.getConfig()
to load our properties. Then, we have to adjust our main method to add the ApplicationListener, so it triggers our Config.getConfig()
on the environment prepared event. Fully finished, it looks somewhat like this:
@SpringBootApplication
public class BlogBackendApplication {
static class EnvironmentPreperation implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
Config.getConfig();
if (Config.USERNAME.isEmpty() || Config.PASSWORD.isEmpty()) {
throw new IncompleteConfigException();
}
}
}
public static void main(String[] args) {
SpringApplication blogBackend = new SpringApplication();
blogBackend.addListeners(new BlogBackendApplication.EnvironmentPreperation());
blogBackend.setSources(new HashSet(Arrays.asList(BlogBackendApplication.class)));
ConfigurableApplicationContext context = blogBackend.run(args);
System.out.println("DbUsername: " + Config.USERNAME + " ; DbPassword: " + Config.PASSWORD);
}
}
I have added that last line of code to make sure that the properties are loaded correctly. When running the code, I see this beautiful piece of log appearing in my console:
2020-07-17 20:07:05.519 INFO 14676 --- [ restartedMain] e.r.blogbackend.BlogBackendApplication : Started BlogBackendApplication in 2.4 seconds (JVM running for 2.981)
DbUsername: <username> ; DbPassword: <password>
Now that I have secured my database credentials, I can start working on connecting my MongoDB database to my Spring Boot project. So, next time, I will start implementing and adding my first test blog posts into the database.
Next up in Building a Blog: Insert Data in MongoDB with Spring Boot