¿Cómo usar la contraseña encriptada en apache BasicDataSource?

En este momento, guardo la contraseña [sin cifrar] en un archivo de propiedades. Esta contraseña se coloca como está en la configuración xml usando ant.
[La configuración xml es para fuente de datos, está creando el objeto de dbcp.BasicDataSource]

Ahora, es posible que después del objective ant, la contraseña se copie en forma encriptada. ¡Oí que el Jasypt puede hacer eso! Hasta ahora no he probado esto. Pero, el problema no termina aquí. BasicDataSource no acepta contraseña encriptada. ¿Hay algún reemplazo para BasicDatasource.

FYI: Estoy usando Spring, si eso importa.

Con Spring hay una mejor manera: use la clase PropertyPlaceholderConfigurer .

  classpath:com/foo/jdbc.properties            

Cuando especifica una subclase de PropertiesPersister en el marcador de posición de la propiedad, Spring carga jdbc.properties y descifra el archivo utilizando esa clase. Tal vez algo así como:

 public class MyPropertyPersister extends DefaultPropertiesPersister { // ... initializing stuff... public void load(Properties props, InputStream is) throws IOException { Cipher decrypter = getCipher(); InputStream cis = new CipherInputStream(is, decrypter); super.load(props, cis); } public void load(Properties props, Reader reader) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); IOUtils.copy(reader, baos); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); Cipher decrypter = getCipher(); InputStream cis = new CipherInputStream(bais, decrypter); InputStreamReader realReader = new InputStreamReader(cis); super.load(props, realReader); } public void loadFromXml(Properties props, InputStream is) throws IOException { Cipher decrypter = getCipher(); InputStream cis = new CipherInputStream(is, decrypter); super.loadFromXml(props, cis); } private Cipher getCipher() { // return a Cipher to read the encrypted properties file ... } ... } 

Espero eso ayude.

EDITAR Si usa Jasypt, no necesita definir ninguna PropertiesPersister . De la documentación de Jasypt :

Jasypt proporciona una implementación de estas clases Spring relacionadas con la configuración que pueden leer archivos .properties con valores encriptados (como los administrados por la clase EncryptableProperties) y manejarlos de manera transparente para el rest de los beans de la aplicación Spring.

Con esto, puede definir jdbc.properties como este

  jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost/reportsdb jdbc.username=reportsUser jdbc.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm) 

y la configuración de Spring puede ser así

              /WEB-INF/classes/jdbc.properties          

De esta forma, puede poner la contraseña para descifrar la propiedad oculta en una variable de entorno cuando inicia la aplicación y la desarma más tarde.

El siguiente enlace de jasypt explica cómo se puede leer un archivo de propiedades que contiene contenido encriptado desde su aplicación:

http://www.jasypt.org/encrypting-configuration.html

Para crear el archivo de propiedades desde ANT, mi sugerencia es usar la tarea groovy de la siguiente manera:

   import org.jasypt.encryption.pbe.StandardPBEStringEncryptor def encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword("secret"); def f = new File("config.properties") f.println "datasource.driver=com.mysql.jdbc.Driver" f.println "datasource.url=jdbc:mysql://localhost/reportsdb" f.println "datasource.username=reportsUser" f.println "datasource.password=ENC("+encryptor.encrypt("dbpassword")+")"  

No es del todo cierto en el caso de BasicDataSource .

Si lee los javadocs para BasicDataSource , setPassword() no tiene efecto una vez que se ha inicializado el grupo. El grupo se inicializa la primera vez que se invoca uno de los siguientes métodos: getConnection , setLogwriter , setLoginTimeout , getLoginTimeout , getLogWriter .

Ref: http://www.docjar.com/html/api/org/apache/commons/dbcp/BasicDataSource.java.html

Todos estos métodos llaman a createDataSource() eventualmente.

Entonces su nueva clase BasicDataSource solo necesita reemplazar el método createDataSource() Algo como esto:

 public class NewBasicDataSource extends BasicDataSource { protected synchronized DataSource createDataSource() throws SQLException { String decryptedPassword = decryptPassword( super.getPassword() ); super.setPassword( decryptedPassword ); return super.createDataSource(); } private String decryptPassword( String password ) { return //logic to decrypt current password } } 

Extienda BasicDataSource, anule los métodos setPassword y setUserName. Descifra los valores en esos métodos y pásalos a los métodos de superclase.

Cree una nueva tarea ampliando la tarea existente Copy (responsable de la copia de archivo). Cree un nuevo tipo ampliando FilterSet (responsable del filtrado de tokens).
mira el código aquí: – ¿Cómo crear un elemento nested para la tarea ant?

build.xml

         

blah-blah.properties

 property1=value1 property2=value2 PASSWORD=^&YUII%%&*( USERNAME=rjuyal CONNECTION_URL=... someotherproperty=value 

configuración xml

   com.ibm.db2.jcc.DB2Driver   @CONNECTION_URL@   @USERNAME@   @PASSWORD@   true   10   10   ... ... ... 

Después de la ejecución del objective, el xml se copia con los valores del archivo de propiedades. La contraseña será encriptada.

Esto manejará la contraseña encriptada. EncryptionAwareDataSource

 public class EncryptionAwareDataSource extends BasicDataSource{ @Override public synchronized void setPassword(String password) { super.setPassword(Encryptor.getDecryptedValue( password )); } } 

Que todos 😉