2010-08-06 11 views
14

Obecnie przechowuję hasło [niezaszyfrowane] w pliku właściwości. To hasło zostanie umieszczone tak jak w konfiguracji xml za pomocą ant.
[xml konfiguracja jest źródłem danych, to tworzy przedmiot dbcp.BasicDataSource]Jak używać zaszyfrowanego hasła w apache BasicDataSource?

Teraz jest możliwe, że po ant celu hasło jest kopiowane w postaci zaszyfrowanej. Słyszałem, że Jasypt to potrafi! Do tej pory nie próbowałem tego. Ale problem nie kończy się tutaj. BasicDataSource nie akceptuje zaszyfrowanego hasła. Czy istnieje zamiennik dla BasicDatasource.

FYI: Używam Springa, jeśli to ma znaczenie.

Odpowiedz

2

utworzyć nowe zadanie poprzez rozszerzenie istniejącego zadania Copy (odpowiedzialny za kopiowania plików). Utwórz nowy typ przez rozszerzenie FilterSet (odpowiedzialny za filtrowanie tokenów).
zobaczyć kod tutaj: - 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 

konfiguracyjnym 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>@[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> 
... 
... 
... 

Po wykonaniu celu xml jest kopiowany z wartościami z pliku właściwości. Hasło zostanie zaszyfrowane.

To zajmie zaszyfrowane hasło. EncryptionAwareDataSource

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

To wszystko;)

3

Poniższy jasypt Link wyjaśnia, jak plik właściwości zawierający zaszyfrowane treści można odczytać z poziomu aplikacji:

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

Aby utworzyć właściwości pliku od wewnątrz ANT moja propozycja jest użycie Groovy zadanie jako to:

<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

Rozszerz BasicDataSource, zastąp metody setPassword i setUserName. Odszyfruj wartości w tych metodach i przekaż je do metod superklasowych.

16

Ze sprężyną 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> 

Po określeniu podklasę PropertiesPersister w zastępczym nieruchomości, Wiosna załadować jdbc.properties i odszyfrować plik przy użyciu tej klasy. Może coś takiego:

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

EDIT Jeśli używasz Jasypt, nie trzeba definiować żadnych PropertiesPersister. Od Jasypt documentation:

Jasypt zapewnia implementację tych klas Wiosna związane konfiguracyjnych, które potrafią czytać .properties pliki z zaszyfrowanych wartości (jak te zarządzanych przez klasę EncryptableProperties) i obsługiwać je w sposób przejrzysty do reszty wiosnę fasola aplikacji.

Dzięki temu można zdefiniować jdbc.properties jak ten

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

i wiosna config może być 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> 

ten sposób można umieścić hasło do odszyfrowania ukrytą właściwość w zmiennej środowiskowej po uruchomieniu aplikacji i anulowaniu jej później.

+2

bardzo pomocne. Prosta korekta, w pliku właściwości to jdbc.driver, ale w definicji komponentu bean jest to $ {jdbc.driverClassName}. – jbird

3

Nie do końca prawdziwe w przypadku BasicDataSource.

Jeśli czytasz javadocs dla BasicDataSource, setPassword() nie ma żadnego efektu po zainicjowaniu puli.Pula jest inicjowana po raz pierwszy, gdy wywoływana jest jedna 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 zadzwonić createDataSource() ostatecznie.

Więc nowa klasa BasicDataSource tylko musi zastąpić metodę 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 
    } 
} 
Powiązane problemy