Spring jdbc with password encryption

 

                            NOTE: Source Code available for download at the bottom of the page

 
What are we going to learn?
   We will learn how to use encrypted passwords with Spring JdbcDaoSupport for implementing our database operations. 
 
What's needed?
  • Maven
  • JDK 1.5 or higher
  • eclipse 
  • mySQL database
Overall design
  • We will create a employee table to store the employee information.
  • Create DataSource Spring bean with required db parameters
  • Inject the DataSource in to jdbctemplate
  • Create Insert and Select operations on employee with the help of JdbcDaoSupport
  • Load the Spring application context and access the DAO bean to invoke DAO methods
 
Let's get started.
 
Create a maven project of artifact "maven-archetype-quickstart" as shown here. Remember to select the correct artifact "maven-archetype-quickstart" as shown below.
 
artificat selection
 
 
Update the dependencies in pom file.
 
For Spring context jars 
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>4.0.0.RELEASE</version>
</dependency>
 
For Spring JDBC jars
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jdbc</artifactId>
	<version>4.0.0.RELEASE</version>
</dependency>
 
For mySQl connector/driver
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.28</version>
</dependency>
 
 
Employee Model Class
package com.javavision.SpringJDBC.model;

public class Employee {
	public String name;
	public long employeeId;
	public int age;
	
	public Employee(){
		
	}
	
	public Employee(String name, long employeeId, int age) {
		super();
		this.name = name;
		this.employeeId = employeeId;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public long getEmployeeId() {
		return employeeId;
	}
	public void setEmployeeId(long employeeId) {
		this.employeeId = employeeId;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
}
 
This will act as our model object for communication with DAO.
 
 
Create an interface EmployeeDAO to define the dao operations.
 
EmployeeDAO 
package com.javavision.SpringJDBC.dao;

import com.javavision.SpringJDBC.model.Employee;

public interface EmployeeDAO {
	
	public int insertEmployee(Employee employee);
	public Employee getEmployee( long employeeId );

}
 
 
Create implementation class EmployeeDAOImpl
 
 
EmployeeDAOImpl 
package com.javavision.SpringJDBC.dao;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.javavision.SpringJDBC.model.Employee;

public class EmployeeDAOImpl extends JdbcDaoSupport implements EmployeeDAO {

	public int insertEmployee(Employee employee) {
		
		String insert_employee = "INSERT INTO employee(employee_id,name,age)VALUES(?,?,?);";
		int count = getJdbcTemplate().update( insert_employee,
				new Object[] { employee.getEmployeeId(), employee.getName(),employee.getAge() });
		return count;
	}

	public Employee getEmployee(long employeeId) {
		Employee emp;
		try {
			emp = getJdbcTemplate().queryForObject(
					"select * from employee where employee_id = " + employeeId,
					new RowMapper<Employee>() {
						public Employee mapRow(ResultSet rs, int rownumber)
								throws SQLException {
							Employee e = new Employee();
							e.setEmployeeId(rs.getLong("employee_id"));
							e.setName(rs.getString("name"));
							e.setAge(rs.getInt("age"));
							return e;
						}
					});
		} catch (EmptyResultDataAccessException e) {
			return null;
		}
		return emp;
	}
}
                            NOTE: There is no need to define JdbcTemplate
 
 
Create a wrapper class for org.springframework.jdbc.datasource.DriverManagerDataSource which will be used for providing the database connections. This class will be responsible for decrypting the encrypted password provided in the data source in application-context file.
 
getConnectionFromDriverManager is overriden which is responsible for providing the db connection.
 
DecryptPassword is the class which has the code for decrypting the encrypted password.
 
SecureDataSource.java
package com.visionjava.SpringJDBCWithPasswordEncryption.datasource;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.springframework.jdbc.datasource.DriverManagerDataSource;

/**
 * SecureDataSource is a wrapper around DriverManagerDataSource. The encrypted
 * password read from the property file is decrypted while requesting for a
 * connection.
 * 
 * @author visionjava
 * 
 */
public class SecureDataSource extends DriverManagerDataSource {
	private String url;
	private String username;
	private String password;
	private boolean autoCommit;

	
	@Override
	protected Connection getConnectionFromDriverManager(String url,
			Properties props) throws SQLException {
		try {

			String decryptedPassword;
			decryptedPassword = DecryptPassword.decrypt(password);

			Properties properties = new Properties(); // Create Properties
			properties.put("user", username); // Set user ID for connection
			properties.put("password", decryptedPassword); // Set password for connection
			return super.getConnectionFromDriverManager(url, properties);
		} catch (InvalidKeyException e) {			
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {			
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {			
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {			
			e.printStackTrace();
		} catch (BadPaddingException e) {			
			e.printStackTrace();
		} catch (IOException e) {			
			e.printStackTrace();
		}
		return null;
	}

	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}

	public boolean isAutoCommit() {
		return autoCommit;
	}
	public void setAutoCommit(boolean autoCommit) {
		this.autoCommit = autoCommit;
	}	
}
 
 
 
DecryptPassword.java
package com.visionjava.SpringJDBCWithPasswordEncryption.datasource;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;

public class DecryptPassword {	
	public static String decrypt(String encryptedPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException, InvalidKeyException{
			
	sun.misc.BASE64Decoder base64decoder = new BASE64Decoder(); 
	byte[] encrypedPwdBytes;
	byte[] plainTextPwdBytes = null;
	Cipher cipher = Cipher.getInstance("AES");
        final SecretKeySpec secretKey = new SecretKeySpec("KEYFORVISOSYSTEM".getBytes("UTF-8"), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        plainTextPwdBytes = cipher.doFinal(base64decoder.decodeBuffer(encryptedPassword));
        return new String(plainTextPwdBytes);
	}	
}
 
 
Class to generate encrypted password.
 
EncryptPassword.java
package com.visionjava.SpringJDBCWithPasswordEncryption.datasource;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Encoder;

public class EncryptPassword {
	
	public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalStateException, IllegalBlockSizeException, BadPaddingException, IOException  {
		
		sun.misc.BASE64Encoder base64encoder = new BASE64Encoder();
		SecretKeySpec key = new SecretKeySpec("KEYFORVISIOSYSTEM".getBytes("UTF-8"), "AES");
		byte[] passwordBytes = "password".getBytes("UTF8"); 
		Cipher cipher = Cipher.getInstance("AES"); // cipher is not thread safe  
		cipher.init(Cipher.ENCRYPT_MODE, key);  

		String encrypedPwd = base64encoder.encode(cipher.doFinal(passwordBytes));  
		System.out.println(encrypedPwd);
	}
	
}
 
 
Create the application context.
 
application-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
	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-2.5.xsd">
 
	 <bean id="employeeDAO" class="com.visionjava.SpringJDBCWithPasswordEncryption.dao.EmployeeDAOImpl">
        <property name="jdbcTemplate" ref="myJdbcTemplate"/>
    </bean>   
    
     <bean id="myJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg ref="dataSource"/>
    </bean>
    
    <bean id="dataSource" class="com.visionjava.SpringJDBCWithPasswordEncryption.datasource.SecureDataSource"> 
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/employeestore" />
		<property name="username" value="root" />
		<property name="password" value="IVwDqkt7No/hLGpxdlPblg==" />
	</bean>
</beans>
 
 
 
Let's put everything together.
 
Main class to load the spring application context and call the DAO methods.
 
MainCaller.java
package com.javavision.SpringJDBC;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.javavision.SpringJDBC.dao.EmployeeDAO;
import com.javavision.SpringJDBC.model.Employee;


public class MainCaller {

	public static void main(String[] args) {
		
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
				"application-context.xml");
		EmployeeDAO employeeDAO = (EmployeeDAO)applicationContext.getBean("employeeDAO");
		
		Employee e1 = new Employee("Dan", 123, 20);
		int count = employeeDAO.insertEmployee(e1);
			
		Employee retrievedEmployee = employeeDAO.getEmployee(123);
		System.out.println("Retrieved Employee :: " + retrievedEmployee.getEmployeeId() + " ,"
				+ retrievedEmployee.getName() + " ,"
				+ retrievedEmployee.getAge());

	}

}
 
 
 
 
Project Structure:
 
 
spring jdbc password encryption
 
 
Source Code : SpringJDBCWithPasswordEncryption.rar
Web Analytics