Encrypt Spring Datasource Password
Password encryption is first mandatory field that should be encrypted in application and it does not matter what kind of framework you are using. In this tutorial I will show you how to encrypt password in Spring based application. You probably may have seen many documentation and API which can be use to encrypt password in Spring properties file. Here I will show you simple technique to encrypt password without doing much coding and easy to understand. Although password encryption part is simple but to understand better I will create small Spring MVC web application and will make one call to database to verify if everything works.
Note: To keep this application simple and easy to understand I will use Base64 to encrypt the password. It’s not advisable to use Base64 technique to encrypt the password. I have written many encryption technique for encryption as you could see in these tutorial.
Tools needed:
- Eclipse
- MySQL
- JDK 1.8
- Maven 3.2
Steps:
- Create sample table in MySQL database and insert some dummy data:
CREATE TABLE javahonk.person( firstName varchar(50) NOT NULL, lastName varchar(45) DEFAULT NULL, location varchar(45) DEFAULT NULL, PRIMARY KEY (firstName) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- Insert data:
INSERT INTO `javahonk`.`person` (`firstName`, `lastName`, `location`) VALUES ('Java','Honk','NY'), ('Java2','Honk2','NY'),('Java3','Honk3','NY')
- Create maven project name SpringPasswordEncryption below is final project structure:
- web.xml:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dispatcher-servlet.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
- pom.xml:
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javahonk</groupId> <artifactId>SpringPasswordEncryption</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>SpringPasswordEncryption Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <junit.version>3.8.1</junit.version> <SpringVersion>4.0.6.RELEASE</SpringVersion> <spring-jdbc.version>4.0.6.RELEASE</spring-jdbc.version> <json.version>20140107</json.version> <jackson.version>1.9.10</jackson.version> <log4j.version>1.2.16</log4j.version> <jtds.version>1.2</jtds.version> <servlet.version>3.1.0</servlet.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> </dependency> <!-- Spring dependencies --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${SpringVersion}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${SpringVersion}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${SpringVersion}</version> </dependency> <!-- Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring-jdbc.version}</version> </dependency> <!-- Jackson JSON Mapper --> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>${json.version}</version> </dependency> <dependency> <groupId>net.sourceforge.jtds</groupId> <artifactId>jtds</artifactId> <version>${jtds.version}</version> </dependency> <!-- MySql 5.5 Connector --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.29</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> </dependencies> <build> <finalName>SpringPasswordEncryption</finalName> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> <version>3.1</version> </plugin> </plugins> </build> </project>
- datasource.properties where we will store the password as you could see below password has been encrypted and displayed here:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/JavaHonk jdbc.username=root jdbc.password=YWRtaW4=
Important: Configuration: In dispatcher-servlet.xml as you see, I have created datasource bean which is using class: com.javahonk.dao.CustomDriverManagerDataSource this class extends DriverManagerDataSource manager class. You will see full details of this class below but this what you need to do in your application to encrypt and decrypt the password.
- dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.javahonk.controller" /> <mvc:annotation-driven/> <context:property-placeholder location="classpath:database/database.properties"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/jsp/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <!-- bind messages.properties --> <bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource"> <property name="basename" value="messages/messages" /> </bean> <bean id="dataSource" class="com.javahonk.dao.CustomDriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="personDao" class="com.javahonk.dao.PersonDAOImpl" /> </beans>
- CustomDriverManagerDataSource.java:
package com.javahonk.dao; import org.apache.tomcat.util.codec.binary.Base64; import org.springframework.jdbc.datasource.DriverManagerDataSource; public class CustomDriverManagerDataSource extends DriverManagerDataSource { public CustomDriverManagerDataSource() { super(); } /* (non-Javadoc) * @see org.springframework.jdbc.datasource.AbstractDriverBasedDataSource#setPassword(java.lang.String) */ public synchronized void setPassword(String encryptedPassword){ super.setPassword(base64Decode(encryptedPassword)); } /** * @param token * @return encoded */ public static String base64Encode(String token) { byte[] encodedBytes = Base64.encodeBase64(token.getBytes()); return new String(encodedBytes); } /** * @param token * @return */ public static String base64Decode(String token) { byte[] decodedBytes = Base64.decodeBase64(token); return new String(decodedBytes); } }
- SpringMVCController.java:
package com.javahonk.controller; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.javahonk.dao.IPersonDAO; @Controller public class SpringMVCController { @Autowired IPersonDAO personDao; @RequestMapping(value = "/databasetest") public @ResponseBody List<Map<String, Object>> databasetest() { return personDao.selectAllPerson(); } }
- IPersonDAO.java:
package com.javahonk.dao; import java.util.List; import java.util.Map; public interface IPersonDAO { List<Map<String, Object>> selectAllPerson(); }
- PersonDAOImpl.java:
package com.javahonk.dao; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; public class PersonDAOImpl implements IPersonDAO { @Autowired private JdbcTemplate jdbcTemplate; @Override public List<Map<String, Object>> selectAllPerson() { String sql = "SELECT * FROM person"; List<Map<String, Object>> listOfPerson = jdbcTemplate.queryForList(sql); return listOfPerson; } }
- These are important file shown here other are included in bottom to download. You could run this application on any server if everything setup correctly. Here I will be using Tomcat server to run this application on MySQL database server. To run this application right click project –> Run As –> Run On Server (Before doing this you will have to download and configure Tomcat server in Eclipse if you have not done yet please follow this tutorial to configure Tomcat in Eclipse). You will see below first page:
- As you remember we have create table in MySQL database and to fetch the data from database we also create one method in SpringMVCController.java its mapping URL is “/databasetest”. Let’s use this in URL to test if we get data from database or not. If everything goes well you will see below output:
Download Project: SpringPasswordEncryption
- For more information on please visit Spring site here