有一种方法可以在xml spring配置文件中隐藏/加密密码吗? 我读过可以使用DataSource的“自定义”子类,但解决方案将密钥保存在与纯文本相同的配置文件中......所以有点无用。
有一种方法可以使用KeyStore吗? 例如,从密钥库中读取值。
谢谢大家。
答案 0 :(得分:12)
隐藏密码的目的是什么?我建议你在容器中配置数据源(Tomcat,JBoss或你使用的任何东西)并使用jndi将数据源注入你的应用程序:
<jee:jndi-lookup id="thedatasource"
jndi-name="java:comp/env/jdbc/thedatasource"
lookup-on-startup="false"
expected-type="javax.sql.DataSource"/>
这样,您不必在应用程序中公开密码,而只在servlet容器中公开密码。
答案 1 :(得分:11)
是的,你可以这样做。您必须在数据源类周围创建一个包装器bean。这是我以前如何做到的一个例子。希望这有帮助!
<beans>
<bean id="someDao" class="com.dao.SomeDAOImpl">
<property name="datasource">
<ref local="secureDataSource"/>
</property>
</bean>
<bean id="secureDataSource" class="com.ds.SecureDataSource">
<property name="driverClassName">
<value><your driver></value>
</property>
<property name="url">
<value><your url></value>
</property>
<property name="username">
<value><your user id></value>
</property>
<property name="password">
<value><encrypted_pwd></value>
</property>
</bean>
</beans>
然后在SecureDataSource类中,您需要解密密码。
import java.sql.Connection;
import java.sql.SQLException;
public class SecureDataSource extends DriverManagerDataSource{
private String url;
private String username;
private String password;
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
protected Connection getConnectionFromDriverManager() throws SQLException {
String decryptedPassword = null;
//decrypt the password here
return getConnectionFromDriverManager(url,username,decryptedPassword);
}
}
答案 2 :(得分:3)
已经给出了很好的选择,另一个明显的答案是使用PropertyPlaceholderConfigurer:
<context:property-placeholder
system-properties-mode="OVERRIDE"
location="classpath:database.properties" />
<bean id="dataSource" class="com.whatever.datasource.you.Use">
<property name="password" value="${database.password}" />
</bean>
现在,您可以将密码保存为属性文件中的属性(如果您不希望在SCM中使用,则可以在部署期间创建)或作为系统属性(希望也可能无法访问)其他开发商)。
澄清: 在部署期间创建有点模糊。我想你必须编写一个安装程序,在最终用户的机器上动态生成属性文件,可能还有一个注册/登录机制。
编辑:我还没弄清楚你是谁隐藏了这些信息。两种理论:
a)有权访问您的源代码的人员 b)您的客户
如果是a),那就走吧。使用调试器启动应用程序的其他开发人员很容易违反所有其他方法(突然他在数据源对象内部并看到密码)。
如果是b),那么基本上你没有机会。客户有很多可能获得你的密码:调试器,代理,字节码操作,加载时间编织等。即使他没有做任何这些,他只需要附加一个端口嗅探器来获取密码清除文本。唯一安全的做法是为每个客户提供一个用户名/密码(永远不要在客户的机器上存储全局密码)。
答案 3 :(得分:0)
我最近有同样的问题。我想在.properties文件中存储密码的哈希版本。
由于以前的选项,我做了诀窍:我扩展了DelegatingDataSource
并覆盖了getConnection([...])
方法。
public class UnhashingDataSource extends DelegatingDataSource {
private static final Logger LOGGER = Logger.getLogger(UnhashingDataSource.class);
private static final int HEX_RADIX = 16;
private static final String DB_PASS = "a_sample_password";
@Override
public Connection getConnection() throws SQLException {
DriverManagerDataSource dataSource = (DriverManagerDataSource) getTargetDataSource();
return getConnection(dataSource.getUsername(), dataSource.getPassword());
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
try {
DataSource datasource = getTargetDataSource();
if (datasource == null) {
throw new RuntimeException("targetDataSource is null");
}
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.reset();
md.update(DB_PASS.getBytes());
if (password.equals(getHexString(md.digest()))) {
return datasource.getConnection(username, DB_PASS);
} else {
throw new RuntimeException("Unable to connect to DB");
}
} catch (NoSuchAlgorithmException e) {
LOGGER.error("Unknown algorithm");
}
return null;
}
private String getHexString(final byte[] messageDigest) {
BigInteger bigInt = new BigInteger(1, messageDigest);
return bigInt.toString(HEX_RADIX);
}
}
然后,这是我在applicationContext.xml
中使用它的方式:
# Using the unhashing datasource
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="unhashingDataSource" />
# ...
</bean>
<bean id="hashedDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${datasource.driverClassName}" />
<property name="url" value="${datasource.url}" />
<property name="username" value="${datasource.username}" />
<property name="password" value="${datasource.hash}" />
</bean>
<bean id="unhashingDataSource"
class="my.package.UnhashingDataSource">
<property name="targetDataSource" ref="hashedDataSource" />
</bean>
datasource.hash
是一个属性(来自.properties文件),其存储方式如下:
datasource.hash = 2e54b0667ef542e3398c55a08a4e04e69b9769e8
普通密码仍然是字节码,但不再直接在.properties文件中。
答案 4 :(得分:0)
感谢您的所有帖子和查询。
希望访问者通过阅读此页面明确加密密码的技术方法。我想在这里添加一件重要的事情,如果您正在处理生产,那么肯定会建议您使用任何“安全哈希算法”,如SHA-256和盐。您可以考虑使用salt作为行业标准的安全哈希算法。