Monday, December 19, 2011

Encrypting the password in the configuration files of MYBATIS

In the configuration file of ORM tools like hibernate , mybatis, jpa we have a common concern that the password of the database is exposed to each and every developer or whoever has the access to the code. It’s a great security concern for the enterprise which has the sensitive data in the database. So there comes the need to have an encrypted password in the configuration file and read it programmatically and make the decrypted password available to the application only at the run time. So that no one can read the password.
We can achieve this through any encryption codec algorithm providers like apache, sun and many more. I am demonstrating here using apache codec which is opensource library to encrypt and decrypt the password. I am demonstrating it for mybatis but the same can be achieved through similar process in hibernate or JPA.
We have a database properties file which contains all the database related properties like username, password, driver and url. The configuration file reads from this property file. We will be storing the password (in encrypted form in this property file) and while reading we will decrypt the password and give it to the builder for creating a sqlSession. To write to the database properties file we will use the command line argument to provide it with the properties file.
Lets have a look at the properties file:
driver=com.ibm.db2.jcc.DB2Driver
url=jdbc:db2://localhost:50000/CDR
username=db2admin
password=VXR!tre6g

Lets have a look at the configuration.xml file.

















]]>



Lets have a look at the PasswordService.java file which will write to the database.properties file and will have functions like encrypt and decrypt the password.
public final class PasswordService {
private static PasswordService instance;

public PasswordService() {
}

public synchronized String encrypt(String plaintext) throws Exception {
if(plaintext != null)
return new String(Base64.encodeBase64(plaintext.getBytes()));
return null;
}

public synchronized String decrypt(String plaintext) throws Exception {
if(plaintext != null)
return new String(Base64.decodeBase64(plaintext.getBytes()));
return null;
}
public static synchronized PasswordService getInstance()
{
if (instance == null) {
instance = new PasswordService();
}
return instance;
}
public static void main(String args[]){
try {
String encryped = getInstance().encrypt(args[0]);
Properties prop = new Properties();
InputStream in = ConnectionFactory.class.getResourceAsStream("prop.properties");
prop.load(in);
Properties databaseprop = PropsUtils.load(prop.getProperty("databasepropertiesfile"));
Enumeration e = databaseprop.keys();
while(e.hasMoreElements()){
String str = (String)e.nextElement();
if(str.equals("password")){
databaseprop.setProperty("password", encryped);
}
}
URL url = ClassLoader.getSystemResource(prop.getProperty("databasepropertiesfile"));
FileOutputStream fos =new FileOutputStream(url.getFile());
databaseprop.store(fos, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}


Lets have a look at the ConnectionFactory.java file which will create the sqlSession.

public class ConnectionFactory {

private static SqlSessionFactory sqlMapper;
private static Reader reader;
static {
try {
Properties prop = new Properties();
InputStream in = ConnectionFactory.class.getResourceAsStream("prop.properties");
prop.load(in);
Properties databaseprop = PropsUtils.load(prop.getProperty("databasepropertiesfile"));
String encrypedPassword = databaseprop.getProperty("password");
String password = PasswordService.getInstance().decrypt(encrypedPassword);
databaseprop.setProperty("password", password);
String conf =prop.getProperty("configurationfile");
reader = Resources.getResourceAsReader(conf);
sqlMapper = new SqlSessionFactoryBuilder().build(reader,databaseprop);

} catch (Exception e) {
e.printStackTrace();
}
}

public static SqlSessionFactory getSession() {
return sqlMapper;
}
}

Lets have a look at the PropUtils.java file

public class PropsUtils {
private PropsUtils() { }
/**
* Load a properties file from the classpath
* @param propsName
* @return Properties
* @throws Exception
*/
public static Properties load(String propsName) throws Exception {
Properties props = new Properties();
URL url = ClassLoader.getSystemResource(propsName);
props.load(url.openStream());
return props;
}

/**
* Load a Properties File
* @param propsFile
* @return Properties
* @throws IOException
*/
public static Properties load(File propsFile) throws IOException {
Properties props = new Properties();
FileInputStream fis = new FileInputStream(propsFile);
props.load(fis);
fis.close();
return props;
}
}

No comments: