The resource definition in tomcat\'s server.xml
looks something like this...
As said before encrypting passwords is just moving the problem somewhere else.
Anyway, it's quite simple.
Just write a class with static fields for your secret key and so on, and static methods to encrypt, decrypt your passwords.
Encrypt your password in Tomcat's configuration file (server.xml
or yourapp.xml
...) using this class.
And to decrypt the password "on the fly" in Tomcat, extend the DBCP's BasicDataSourceFactory
and use this factory in your resource.
It will look like:
<Resource
name="jdbc/myDataSource"
auth="Container"
type="javax.sql.DataSource"
username="user"
password="encryptedpassword"
driverClassName="driverClass"
factory="mypackage.MyCustomBasicDataSourceFactory"
url="jdbc:blabla://..."/>
And for the custom factory:
package mypackage;
....
public class MyCustomBasicDataSourceFactory extends org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory {
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
Object o = super.getObjectInstance(obj, name, nameCtx, environment);
if (o != null) {
BasicDataSource ds = (BasicDataSource) o;
if (ds.getPassword() != null && ds.getPassword().length() > 0) {
String pwd = MyPasswordUtilClass.unscramblePassword(ds.getPassword());
ds.setPassword(pwd);
}
return ds;
} else {
return null;
}
}
Hope this helps.
All of the foregoing having been said, if you still want to avoid plain text passwords you can use a hashing algorithm such as SHA-256 or (preferably) SHA-512. When a password is created, obtain the hashed value and store it rather than the password. When a user logs in, hash the password and see of it matches the stored hashed password. Hashing algorithms take a character string (or number) from a small string (or number) space into a much larger one in a way that is expensive to reverse.
Note:
You can use WinDPAPI to encrypt and decrypt data
public class MyDataSourceFactory extends DataSourceFactory{
private static WinDPAPI winDPAPI;
protected static final String DATA_SOURCE_FACTORY_PROP_PASSWORD = "password";
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception{
Reference ref = (Reference) obj;
for (int i = 0; i < ref.size(); i++) {
RefAddr ra = ref.get(i);
if (ra.getType().equals(DATA_SOURCE_FACTORY_PROP_PASSWORD)) {
if (ra.getContent() != null && ra.getContent().toString().length() > 0) {
String pwd = getUnprotectedData(ra.getContent().toString());
ref.remove(i);
ref.add(i, new StringRefAddr(DATA_SOURCE_FACTORY_PROP_PASSWORD, pwd));
}
break;
}
}
return super.getObjectInstance(obj, name, nameCtx, environment);
}
}