Скрыть пароль источника данных в весеннем XML-файле - PullRequest
12 голосов
/ 16 ноября 2010

есть способ скрыть / зашифровать пароль в конфигурационном файле xml spring?Я читал, что это возможно с «пользовательским» подклассом DataSource, но решения хранят ключ в том же файле конфигурации, что и обычный текст ... так что это немного бесполезно.?Например, прочитайте значение из хранилища ключей.

Спасибо всем.

Ответы [ 5 ]

12 голосов
/ 16 ноября 2010

Какова цель сокрытия пароля?Я предлагаю вам сконфигурировать источник данных в контейнере (Tomcat, JBoss или любой другой, который вы используете) и внедрить источник данных в свое приложение, используя jndi:

<jee:jndi-lookup id="thedatasource"
                     jndi-name="java:comp/env/jdbc/thedatasource"
                     lookup-on-startup="false"
                     expected-type="javax.sql.DataSource"/>

Таким образом, вам не нужно выставлять пароль и пароль в вашем приложении, нотолько в контейнере сервлетов.

11 голосов
/ 16 ноября 2010

Да, вы можете сделать это. Вам нужно будет создать 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);
    }
}
3 голосов
/ 16 ноября 2010

Были заданы хорошие варианты, другой очевидный ответ - использовать 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) или как системное свойство (которое, мы надеемся, также будет недоступно для других разработчиков).

Уточнение: создать во время развертывания несколько расплывчато.Я предполагаю, что вам придется написать установщик, который динамически генерирует файл свойств на компьютере конечного пользователя, возможно, в сочетании с механизмом регистрации / входа.


РЕДАКТИРОВАТЬ: Iдо сих пор не понял, от кого ты скрываешь информацию.Две теории:

а) Люди, которые имеют доступ к вашему исходному коду
б) Ваши клиенты

Если это а), тогда иди по моему пути.Все остальные способы могут быть легко нарушены другим разработчиком, который просто запустит ваше приложение с помощью отладчика (и вдруг он окажется внутри объекта источника данных и увидит пароль).

Если это b), то у вас нет шансов, в основном,У клиента есть масса возможностей получить ваш пароль: отладчики, агенты, манипуляции с байт-кодом, ткачество во время загрузки и т. Д. Даже если он этого не делает, ему просто нужно подключить анализатор портов, чтобы получить пароль в открытом виде.текст.Единственное, что нужно сделать, - это ввести имя пользователя / пароль для каждого клиента (никогда не храните глобальный пароль на компьютере вашего клиента).

0 голосов
/ 22 февраля 2016

Спасибо за все ваши сообщения и запросы.

Надеемся, что посетителям понятен технический способ зашифровать пароль, прочитав эту страницу.Здесь я хотел бы добавить одну важную вещь: если вы имеете дело с производством, то определенно предложите вам использовать любой «безопасный алгоритм хэширования», например SHA-256 с солью.Вы можете рассмотреть алгоритм безопасного хэширования с использованием соли в качестве отраслевого стандарта.

0 голосов
/ 19 октября 2012

У меня недавно был тот же вопрос. Я хотел сохранить хешированную версию пароля в файле .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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...