目前我将密码[未加密]保存在属性文件中。使用ant将该密码放置在配置xml中 [配置xml用于数据源,它正在创建dbcp.BasicDataSource的对象]
现在,在ant目标之后是否有可能以加密形式复制密码。听说Jasypt能做到这一点!直到现在我还没试过这个。但是,问题并没有在这里结束。 BasicDataSource不接受加密密码。是否有BasicDatasource的替代品。
仅供参考:如果重要的话,我正在使用Spring。
答案 0 :(得分:17)
使用Spring有一种更好的方法:使用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>
当您在属性占位符中指定PropertiesPersister的子类时,Spring会加载jdbc.properties
并使用该类解密文件。也许是这样的:
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
...
}
...
}
希望它有所帮助。
修改强>
如果您使用Jasypt,则无需定义任何PropertiesPersister
。来自Jasypt documentation:
Jasypt提供了这些与配置相关的Spring类的实现,它们可以读取带有加密值的.properties文件(如EncryptableProperties类管理的文件),并透明地处理它们的其余Spring应用程序bean。
有了这个,您可以像这样定义jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/reportsdb
jdbc.username=reportsUser
jdbc.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm)
并且Spring配置可能是这样的
<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>
这样,您可以在启动应用程序时将隐藏属性的密码置于环境变量中,稍后再取消设置。
答案 1 :(得分:3)
以下jasypt链接说明了如何从应用程序中读取包含加密内容的属性文件:
http://www.jasypt.org/encrypting-configuration.html
要从ANT中创建属性文件,我的建议是使用groovy任务,如下所示:
<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 :(得分:3)
BasicDataSource
的情况并非完全正确。
如果您阅读BasicDataSource
的javadoc,则{pool}初始化后setPassword()
无效。第一次调用以下方法之一时初始化池:getConnection
,setLogwriter
,setLoginTimeout
,getLoginTimeout
,getLogWriter
。
参考:http://www.docjar.com/html/api/org/apache/commons/dbcp/BasicDataSource.java.html
所有这些方法最终都会调用createDataSource()
。
所以你的新BasicDataSource类只需覆盖方法createDataSource()
像这样:
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 :(得分:2)
扩展BasicDataSource,覆盖setPassword和setUserName方法。解密这些方法中的值并将它们传递给超类方法。
答案 4 :(得分:2)
通过扩展现有任务Copy
(负责文件复制)来创建新任务。通过扩展FilterSet
(负责过滤令牌)来创建新类型
看到这里的代码: -
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
<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>
...
...
...
执行目标后,将使用属性文件中的值复制xml。密码将被加密。
这将处理加密密码。 的 EncryptionAwareDataSource 强>
public class EncryptionAwareDataSource extends BasicDataSource{
@Override
public synchronized void setPassword(String password) {
super.setPassword(Encryptor.getDecryptedValue( password ));
}
}
那个'全部;)