Jak używać zaszyfrowanego hasła w apache BasicDataSource?

Obecnie przechowuję hasło [niezaszyfrowane ] w pliku właściwości. To hasło zostanie umieszczone tak, jak jest w konfiguracji XML za pomocą ant.
[Konfiguracja XML jest dla datasource, jest wytworzeniem obiektu dbcp.BasicDataSource]

Teraz, jest to możliwe, że po Ant target hasło jest kopiowane w formie zaszyfrowanej. Słyszałem, że Jasypt może to zrobić! Do tej pory tego nie próbowałem. Ale problem nie kończy się na tym. BasicDataSource nie akceptuje zaszyfrowanego hasła. Czy istnieje jakiś zamiennik dla BasicDatasource.

FYI: używam wiosny, jeśli to ma znaczenie.

Author: Rakesh Juyal, 2010-08-06

5 answers

Z Springiem jest lepszy sposób: Użyj klasy PropertyPlaceholderConfigurer .

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

Gdy określisz podklasę PropertiesPersister w obiekcie zastępczym właściwości, Spring załaduje jdbc.properties i odszyfruje plik za pomocą tej klasy. Może coś w stylu:

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
         ...
    }
    ...
}
Mam nadzieję, że to pomoże.

EDIT Jeśli używasz Jasypt, nie musisz definiować żadnego PropertiesPersister. Z dokumentacji Jasypt :

Jasypt zapewnia implementacja tych związanych z konfiguracją klas Spring, które mogą czytać .właściwości plików z zaszyfrowanymi wartościami (jak te zarządzane przez klasę EncryptableProperties) i obsługiwać je przejrzyście do reszty aplikacji Spring fasoli.

Za pomocą tego możesz zdefiniować jdbc.properties w ten sposób

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

A Spring config może wyglądać tak

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

W ten sposób możesz umieścić hasło do odszyfrowania ukrytej właściwości w zmiennej środowiskowej po uruchomieniu aplikacji i odłączyć go później.

 17
Author: Ither,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-24 14:49:55

Poniższy link jasypt wyjaśnia, w jaki sposób Plik Właściwości zawierający zaszyfrowaną zawartość można odczytać z poziomu aplikacji:

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

Aby utworzyć plik właściwości z wnętrza ANT proponuję użyć zadania groovy w następujący sposób:

<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>
 3
Author: Mark O'Connor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-08 15:08:53

Nie do końca prawda w przypadku BasicDataSource.

Jeśli czytasz javadocs dla BasicDataSource, setPassword() nie ma wpływu po zainicjowaniu puli. Pula jest inicjalizowana przy pierwszym wywołaniu jednej z następujących metod: getConnection, setLogwriter, setLoginTimeout, getLoginTimeout, getLogWriter.

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

Wszystkie te metody wywołują createDataSource() W końcu.

Więc twoja nowa klasa BasicDataSource musi tylko override the method createDataSource() Coś takiego:

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
    }
}
 3
Author: huydang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-01 08:38:12

Rozszerza BasicDataSource, nadpisuje metody setPassword i setUserName. Odszyfruj wartości w tych metodach i przekaż je metodom klasy super.

 2
Author: Adi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-13 08:26:19

Utwórz nowe zadanie rozszerzając istniejące zadanie Copy (odpowiedzialne za kopiowanie plików). Utwórz nowy typ przez rozszerzenie FilterSet (odpowiedzialne za filtrowanie tokenów).
zobacz kod tutaj:- Jak utworzyć zagnieżdżony element dla zadania ant?

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

Bla-bla.właściwości

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

Konfiguracja xml

<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>@CONNECTION_URL@</value>
        </property>
        <property name="username">
            <value>@USERNAME@</value>
        </property>
        <property name="password">
            <value>@PASSWORD@</value>
        </property>
        <property name="poolPreparedStatements">
            <value>true</value>
        </property>
        <property name="maxActive">
            <value>10</value>
        </property>
        <property name="maxIdle">
            <value>10</value>
        </property>     
    </bean>
...
...
...

Po wykonaniu celu XML jest kopiowany z wartościami z pliku właściwości. Hasło będą zaszyfrowane.

To obsłuży zaszyfrowane hasło. EncryptionAwareDataSource

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

That ' all;)

 2
Author: Rakesh Juyal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:45:56