2010-08-06 7 views
14

Gegenwärtig behalte ich das Passwort [unverschlüsselt] in einer Eigenschaftendatei. Dieses Passwort wird wie in der Konfigurations-XML mit ant angegeben.
[Die XML-Konfiguration ist für Datenquelle, wird das Objekt von dbcp.BasicDataSource schafft]Wie verschlüsselte Passwort in Apache BasicDataSource verwenden?

Nun ist es möglich, dass nach dem ant Ziel wird das Passwort in verschlüsselter Form kopiert. Hab gehört, dass der Jasypt das kann! Bis jetzt habe ich das nicht versucht. Aber das Problem endet hier nicht. BasicDataSource akzeptiert kein verschlüsseltes Passwort. Gibt es einen Ersatz für BasicDatasource?

FYI: Ich benutze Frühling, wenn das zählt.

Antwort

2

eine neue Aufgabe erstellen, indem bestehende Aufgabe erstreckt Copy (verantwortlich für die Datei-Kopie). Erstellen Sie einen neuen Typ durch Erweitern von FilterSet (verantwortlich für das Filtern von Tokens).
sehen Sie den Code hier: - How to create nested element for ant task?

build.xml

<target name="encrypted-copy" > 
     <CopyEncrypted todir="dist/xyz/config" overwrite="true"> 
      <fileset dir="config"/>     
      <encryptionAwareFilterSet> 
       <filtersfile file="conf/properties/blah-blah.properties" /> 
      </encryptionAwareFilterSet> 
     </CopyEncrypted> 
    </target> 

blah-blah.properties

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

xml Konfiguration

<bean id="dataSource" 
     class="com.xyz.datasource.EncryptionAwareDataSource" 
     destroy-method="close" autowire="byName"> 
     <property name="driverClassName"> 
      <value>com.ibm.db2.jcc.DB2Driver</value> 
     </property> 
     <property name="url"> 
      <value>@[email protected]</value> 
     </property> 
     <property name="username"> 
      <value>@[email protected]</value> 
     </property> 
     <property name="password"> 
      <value>@[email protected]</value> 
     </property> 
     <property name="poolPreparedStatements"> 
      <value>true</value> 
     </property> 
     <property name="maxActive"> 
      <value>10</value> 
     </property> 
     <property name="maxIdle"> 
      <value>10</value> 
     </property>  
    </bean> 
... 
... 
... 

Nach der Ausführung des Ziels wird das XML mit Werten aus der Eigenschaftendatei kopiert. Das Passwort wird verschlüsselt.

Dies wird das verschlüsselte Passwort behandeln. EncryptionAwareDataSource

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

Das ist alles;)

3

Der folgende jasypt Link erklärt, wie eine Eigenschaftsdatei verschlüsselten Inhalt enthält, kann aus Ihrer Anwendung gelesen werden:

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

die Eigenschaften-Datei erstellen mein Vorschlag, die groovy Aufgabe zu verwenden ist als folgt:

<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/> 

<groovy> 
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")+")"  

</groovy> 
2

Extend BasicDataSource, außer Kraft setzen und setPassword setUserName Methoden. Entschlüsseln Sie die Werte in diesen Methoden und übergeben Sie sie an Superklassenmethoden.

16

Mit Feder gibt es einen besseren Weg: Verwenden Sie die Klasse.

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="locations"> 
     <value>classpath:com/foo/jdbc.properties</value> 
    </property> 
    <property name="propertiesPersister"> 
     <bean class="com.mycompany.MyPropertyPersister" /> 
    </property>   
</bean> 

<bean id="dataSource" destroy-method="close" 
     class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="${jdbc.driverClassName}"/> 
    <property name="url" value="${jdbc.url}"/> 
    <property name="username" value="${jdbc.username}"/> 
    <property name="password" value="${jdbc.password}"/> 
</bean> 

Wenn Sie eine Unterklasse von PropertiesPersister in der Eigenschaft Platzhalter angeben, lädt Frühling die jdbc.properties und entschlüsselt die Datei, die Klasse. Vielleicht etwas wie:

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 
     ... 
    } 
    ... 
} 

Ich hoffe, es hilft.

EDIT Wenn Sie Jasypt verwenden, Sie brauchen keine PropertiesPersister zu definieren. Von den Jasypt documentation:

Jasypt eine Implementierung dieser konfigurationsbezogene Spring classes bietet die .properties-Dateien mit verschlüsselten Werten lesen kann (wie die, die von der EncryptableProperties Klasse verwaltet werden) und mit ihnen umgehen zu dem Rest des Frühlings transparent Anwendungsbohnen.

Mit diesem können Sie definieren jdbc.properties wie diese

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

und der Frühling Config wie diese

sein kann
<bean class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer"> 
    <constructor-arg> 
    <bean class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor"> 
     <property name="config"> 
     <bean class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig"> 
      <property name="algorithm" value="PBEWithMD5AndDES" /> 
      <property name="passwordEnvName" value="APP_ENCRYPTION_PASSWORD" /> 
     </bean> 
     </property> 
    </bean> 
    </constructor-arg> 
    <property name="locations"> 
    <list> 
     <value>/WEB-INF/classes/jdbc.properties</value> 
    </list> 
    </property> 
</bean> 

<bean id="dataSource" destroy-method="close" 
     class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="${jdbc.driverClassName}"/> 
    <property name="url" value="${jdbc.url}"/> 
    <property name="username" value="${jdbc.username}"/> 
    <property name="password" value="${jdbc.password}"/> 
</bean> 

Auf diese Weise können Sie das Passwort setzen für die verborgene Eigenschaft entschlüsseln in einer Umgebungsvariablen, wenn Sie die Anwendung starten und später wieder aufheben.

+2

Sehr hilfreich. Nur eine triviale Korrektur, in der Eigenschaftendatei ist es jdbc.driver, aber in der Bean-Definition ist es $ {jdbc.driverClassName}. – jbird

3

Nicht ganz zutreffend im Fall von BasicDataSource. Wenn Sie die Javadocs für BasicDataSource gelesen haben, hat setPassword() keine Wirkung, sobald der Pool initialisiert wurde.Der Pool wird initialisiert, wenn eine der folgenden Methoden zum ersten Mal aufgerufen wird: getConnection, setLogwriter, setLoginTimeout, getLoginTimeout, getLogWriter.

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

diese Methoden rufen createDataSource() schließlich alle.

So wird Ihre neue BasicDataSource Klasse braucht nur die Methode createDataSource() So etwas wie dies außer Kraft zu setzen:

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 
    } 
} 
Verwandte Themen