Secure Passwords for Datasources in Spring
Security requirements at my place of employment don’t allow for plain text passwords in any type of configuration files. So we are forced to store passwords encrypted and then decrypt them in every application that needs to create a database connection. This wasn’t an issue for applications that run in a container as Weblogic encrypts the password, but it really limited our use of Spring in non-container apps. To get around this, I’ve created a new subclass of the Spring implementation of javax.sql.Datasource (org.springframework.jdbc.datasource.DriverManagerDataSource) : SecureDriverManagerDataSource which overrides the getPassword() and getConnectionFromDriverManager() methods and adds a new attribute: key. In my implementation of this class, an encrypted password is expected, so before calling the getConnection() method, the password is decrypted using the key attribute. Here is the source code:
public class SecureDriverManagerDataSource extends DriverManagerDataSource
{
private String key;
public String getKey()
{
return key;
}
public void setKey(String key)
{
this.key = key;
}
public String getPassword()
{
if (getKey() == null)
{
throw new RuntimeException("Key Value is not set");
}
try
{ // possible future enhancement, allow user to set which type of encryption to use for this class
return SimpleAESEncrypter.decrypt(super.getPassword(),getKey());
}
catch (SimpleAESEncrypterException e)
{
throw new RuntimeException(e.getMessage(),e);
}
}
protected Connection getConnectionFromDriverManager() throws SQLException
{
return getConnectionFromDriverManager(getUrl(),getUsername(), getPassword());
}
}
And the Spring Bean Defininition:
<bean id="secureDataSource" class="com.mattluce.db.SecureDriverManagerDataSource" lazy-init="true">
<property name="driverClassName">
<value>com.sybase.jdbc2.jdbc.SybDriver</value>
</property>
<property name="url">
<value>jdbc:sybase:Tds:dbserver:1234</value>
</property>
<property name="username">
<value>dbuser</value>
</property>
<property name="password">
<value>x345sdfxxxdasdf==</value>
</property>
<property name="key">
<value>rxxrt56xxc5uuEO/A==</value>
</property>
</bean> This implemenation uses our AES encryption utility, but it could be modified to set the encryption implentation as another attribute of the Datasource. You could then set that in the Spring Bean Definition as well ![]()
August 16th, 2005 at 9:36 am
What the point of this schema if key is available in the same config file as a plain text???
At least use Java keystore, which is protected or something similar.
August 16th, 2005 at 10:10 am
I agree, it’s a bit pointless. It’s really only a method for obfuscation. We have security requirements that don’t allow plain text passwords in files, but this method is acceptable.
August 16th, 2005 at 10:11 am
Hi Dmitri. I agree with you in principal but the idea of using 2-way encryption is part of the ‘Defense in depth‘ strategy. Encrypting the password and separating the key makes it a little harder for someone to get access to the database. The key needed to decrypt could be placed in a directory where you can use UNIX permissions to restrict access - It’s not perfect but you are adding layers of security.
August 16th, 2005 at 11:52 am
See my further comments in Vinnie’s blog:
http://www.j2eegeek.com/blog/2005/08/15/spring-and-encrypted-datasource-passwords/
August 22nd, 2005 at 10:24 am
See further Comments at http://dnene.com/archives/7
March 8th, 2006 at 5:11 pm
For situations where inheriting is not an option like Matt did with DriverManagerDataSource.
For example if you are using c3p0 ComboPooledDataSource which is declared as final, Spring MethodInvokingFactoryBean factory can be used as below..