Скрыть пароль источника данных в файле spring xml
есть способ скрыть / зашифровать пароль в файле конфигурации XML spring? Я читал, что это возможно с "пользовательским" подклассом DataSource, но решения хранят ключ в том же конфигурационном файле, что и обычный текст...так что немного бесполезно.
есть способ использовать KeyStore для этого? Например, прочитайте значение из хранилища ключей.
спасибо всем.
5 ответов
Да, вы можете сделать это. Вам нужно будет создать Боб-оболочку вокруг класса источника данных. Вот пример, как я делал это раньше. Надеюсь, это поможет!
<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);
}
}
какова цель сокрытия пароль? Я предлагаю вам настроить источник данных в контейнере (Tomcat, JBoss или что вы используете) и ввести источник данных в приложение с помощью jndi:
<jee:jndi-lookup id="thedatasource"
jndi-name="java:comp/env/jdbc/thedatasource"
lookup-on-startup="false"
expected-type="javax.sql.DataSource"/>
таким образом, вы не должны выставлять и пароль в своем приложении, но только в контейнере сервлета.
хорошие варианты были даны, еще один очевидный ответ-использовать 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), либо как системное свойство (которое, надеюсь, также будет вне досягаемости других разработчиков).
пояснение: создать во время развертывания несколько смутный. Я думаю, вам придется написать установщик, который генерирует файл свойств динамически на машине конечного пользователя, вероятно, в сочетании с механизмом регистрации / входа.
EDIT: Я до сих пор не понял, от кого вы скрываете информацию. Две теории:--4-->
a) люди, которые имеют доступ к вашему исходному коду
б) ваши клиенты
Если это a), тогда идите моим путем. Все другие пути могут быть легко нарушены другим разработчик просто запускает ваше приложение с отладчиком (и вдруг он находится внутри объекта datasource и видит пароль).
Если это b), то у вас нет шансов, в основном. У клиента есть множество возможностей получить ваш пароль: отладчики, агенты, манипуляции байт-кодом, ткачество loadtime и т. д. Даже если он не сделает ничего из этого, ему просто нужно будет прикрепить сниффер порта, чтобы получить пароль в ясном тексте. Единственная безопасная вещь - иметь имя пользователя / пароль на клиент (никогда не храните глобальный пароль на компьютере вашего клиента).
недавно у меня был тот же вопрос. Я хотел сохранить хэшированную версию пароля в a .файл свойств.
Я сделал трюк благодаря предыдущим вариантам: я расширил 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
является свойством (от a .файл свойств) хранится как:
datasource.hash = 2e54b0667ef542e3398c55a08a4e04e69b9769e8
простой пароль все еще находится в байт-коде, но не непосредственно в a .файл свойств больше.
Спасибо за все ваши сообщения и запросы.
надеюсь, для посетителей его ясно технический способ шифрования пароля, прочитав эту страницу. Одна важная вещь, которую я хотел бы добавить здесь, Если вы имеете дело с производством, то определенно предложит вам использовать любой "безопасный алгоритм хэша", такой как SHA-256 с солью. Вы можете рассмотреть безопасный алгоритм хэша, используя соль в качестве отраслевого стандарта.