Использование закодированного пароля для источника данных, используемого в spring applicationContext.xml

Я хочу сохранить закодированный пароль в моем ниже упомянутом springApplicationContext.xml

Есть ли способ добиться этого?

в настоящее время я настроил все свойства, используя свойство-заполнитель, как показано ниже, но необработанный пароль все еще открыт в моей базе данных.

SpringApplicationContext.xml

<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <beans:property name="driverClassName"><beans:value>${db.driverClassName}</beans:value></beans:property>
        <beans:property name="url"><beans:value>${db.url}</beans:value></beans:property>
        <beans:property name="username"><beans:value>${db.username}</beans:value></beans:property>
        <beans:property name="password"><beans:value>${db.password}</beans:value></beans:property>
</beans:bean>

но фактические значения присутствуют в моем database.properties

db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost/myDB
db.username=root
db.password=root

Я хочу что-то вроде ниже:

springApplicationContext.xml (то же, что и выше)

<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <beans:property name="driverClassName"><beans:value>${db.driverClassName}</beans:value></beans:property>
        <beans:property name="url"><beans:value>${db.url}</beans:value></beans:property>
        <beans:property name="username"><beans:value>${db.username}</beans:value></beans:property>
        <beans:property name="password"><beans:value>${db.password}</beans:value></beans:property>
</beans:bean>

Но значение свойства пароля должно быть в зашифрованном формате в моем database.properties

db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost/myDB
db.username=root
db.password=3g6n72ef8x (using any encription method).

и мой источник данных внутренне расшифровывает пароль перед созданием нового подключения к БД.

Очень признателен за любую помощь/предложение в этом.


person Sandy    schedule 11.10.2012    source источник
comment
Подход, который вы предложили ниже, отлично работает, когда вы можете взять закодированную строку и декодировать ее напрямую. Но для настоящего шифрования вы не можете взять зашифрованную строку и просто расшифровать ее: вы берете пароль в виде открытого текста, шифруете его и сравниваете с уже зашифрованным значением. Например, см. org.springframework.security.crypto.password.StandardPasswordEncoder, который чем-то похож на то, что вы, вероятно, будете использовать после того, как перейдете к кодировщику base64. Итак, вопрос: как ваш DataSource получает фактический пароль для проверки на соответствие зашифрованному значению db.password?   -  person Jay    schedule 11.10.2012
comment
На самом деле требование состояло в том, чтобы не держать необработанный пароль открытым в моем файле database.properties. Следовательно, мой CustomDataSource декодирует закодированное значение файла database.properties, а затем использует его для создания нового подключения к базе данных.   -  person Sandy    schedule 15.10.2012
comment
Я бы сказал, что пароль в кодировке base64 по сути такой же, как необработанный пароль (то есть небезопасный), но я полагаю, что семантика требования должна решаться создателями требований.   -  person Jay    schedule 15.10.2012


Ответы (5)


Это может быть забавно, что я отвечаю на свой собственный вопрос. но все же я просто хотел рассказать о своем решении другим, кто мог столкнуться с такой же проблемой.

для простоты я использовал BASE64Encoder и BASE64Decoder. позже я изменю свой код, чтобы использовать безопасный/лучший алгоритм шифрования/дешифрования.

Я закодировал свой пароль базы данных (например, root для моего случая), используя следующий код:

private String encode(String str) {
        BASE64Encoder encoder = new BASE64Encoder();
        str = new String(encoder.encodeBuffer(str.getBytes()));
        return str;
    }

и поместил закодированный пароль в файл database.properties, как показано ниже:

до

db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost/myDB
db.username=root
db.password=root

после

db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost/myDB
db.username=root
db.password=cm9vdA==  (Note: encoded 'root' by using BASE64Encoder)

Теперь я написал класс-оболочку для org.apache.commons.dbcp.BasicDataSource и переопределил метод setPassword():

import java.io.IOException;
import org.apache.commons.dbcp.BasicDataSource;
import sun.misc.BASE64Decoder;

public class MyCustomBasicDataSource extends BasicDataSource{

    public CustomBasicDataSource() {
        super();
    }

    public synchronized void setPassword(String encodedPassword){
        this.password = decode(encodedPassword);
    }

    private String decode(String password) {
        BASE64Decoder decoder = new BASE64Decoder();
        String decodedPassword = null;
        try {
            decodedPassword = new String(decoder.decodeBuffer(password));
        } catch (IOException e) {
            e.printStackTrace();
        }       
        return decodedPassword;
    }
}

Таким образом, я расшифровываю (BASE64Decoder) закодированный пароль, указанный в файле database.properties.

а также изменил атрибут класса моего компонента dataSource, упомянутого в файле springApplicationContext.xml.

<beans:bean id="dataSource" class="edu.config.db.datasource.custom.MyCustomBasicDataSource" destroy-method="close">
    <beans:property name="driverClassName"><beans:value>${db.driverClassName}</beans:value></beans:property>
    <beans:property name="url"><beans:value>${db.url}</beans:value></beans:property>
    <beans:property name="username"><beans:value>${db.username}</beans:value></beans:property>
    <beans:property name="password"><beans:value>${db.password}</beans:value></beans:property>

Thanks.

person Sandy    schedule 11.10.2012
comment
Вам не нужно делать super.password =decode(encodedPassword); вместо this.password= decode(encodedPassword); - person Ahmad; 09.10.2013
comment
Base64 - это не шифрование, это кодирование! Хотя кодирование имени пользователя и пароля с помощью алгоритма Base64 обычно делает их нечитаемыми невооруженным глазом, они так же легко декодируются, как и кодируются. Безопасность не является целью этапа кодирования. Скорее, целью кодирования является кодирование несовместимых с HTTP символов, которые могут быть в имени пользователя или пароле, в те, которые совместимы с HTTP. - person Omar Elfada; 09.09.2015
comment
Это решение выполняет кодировку пароля base 64 в вашем файле свойств, но он НЕ зашифрован! Я скопировал cm9vdA== в base64decode.org и сразу же получил root. Ради того, чтобы другие читали этот вопрос и ответ, измените вопрос, чтобы задать вопрос «Как использовать пароль с кодировкой base 64» вместо «Как использовать зашифрованный пароль», потому что этот ответ определенно не шифрует его. Я не хочу, чтобы другие читатели думали, что кодирование — это то же самое, что и шифрование. - person Jay; 12.11.2015

Создайте настраиваемый PropertyPlaceHolderConfigurer, расширяющий Spring PropertyPlaceHolderConfigurer.

public class PropertyPlaceholderConfigurer extends
        org.springframework.beans.factory.config.PropertyPlaceholderConfigurer {

    @Override
    protected String convertPropertyValue(final String originalValue) {
        if (originalValue.startwith("SomeText:")) {
            //Apply the decryption logic
            ...
        }
    }
}

Вы можете зашифровать свойства и добавить SomeText:. Используйте этот настроенный PropertyPlaceHolderConfigurer для загрузки свойств

person Sujith    schedule 11.10.2012

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

Обычный метод решения этой более серьезной проблемы хранения рабочих учетных данных состоит в том, чтобы сделать учетные данные частью вашей среды, а не частью вашего исходного кода. Вот несколько способов сделать это:

  • Поместив файл свойств (с незашифрованными паролями) в путь к классам веб-сервера в рабочей среде, таким образом, доступ к этому паролю будет контролироваться доступом к рабочей машине.
  • Храните свойства в web.xml(параметр контекста с именем параметра), опять же, этот файл является частью среды, в которой вы запускаете свой код, и не распространяется вместе с вашим кодом — доступ к этому файлу контролируется доступом к машине.
  • Используйте JNDI и настройте этот ресурс на своем сервере приложений.
person Jay    schedule 11.10.2012
comment
У меня аналогичная ситуация выше, и мы хотим зашифровать пароли в файле свойств, потому что часть нашего приложения установлена ​​на клиентском сервере вместе с другим нашим приложением. Этот агент использует базу данных другого приложения. Мы не хотим, чтобы наши клиенты имели доступ к базе данных этого приложения. Таким образом, существует сценарий, в котором потребуются зашифрованные пароли в файлах свойств. - person Brett Slocum; 29.08.2013
comment
Это интересный сценарий, который я не рассматривал, спасибо. - person Jay; 30.08.2013
comment
Это по-прежнему создает только видимость и теплую дымку безопасности, поскольку любой зашифрованный пароль может быть в конечном итоге расшифрован определенной стороной. Но это остановит случайную вечеринку, этого, вероятно, достаточно. - person Brett Slocum; 30.08.2013
comment
Есть еще один сценарий, в котором приложение является автономным. Раньше я работал в компании, у которой было программное обеспечение с точно такой же ситуацией, как описано выше, но это было отдельное настольное приложение =) - person Gabriel Câmara; 11.11.2015

Создайте класс-оболочку, реализующий интерфейс Datasource, который делегирует вызовы методов базовому источнику данных, но перед этим расшифровывает пароль.

person Abhinav Sarkar    schedule 11.10.2012
comment
Спасибо Abhinav за то, что предложил меня. Теперь я могу добиться этого, используя CustomBasicDataSource. - person Sandy; 11.10.2012