Где я должен хранить учетные данные моей базы данных?

Хорошо ли хранить имя пользователя и пароль базы данных в XML файле и импортировать его в файл безопасности безопасности spring? есть ли лучший вариант? Если мне нужно зашифровать пароль, как это сделать, и как найти зашифрованную версию пароля на phpMyAdmin? MySQL

Логин-service.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

   <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">

    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost/muDB" />
    <property name="username" value="jack" />
    <property name="password" value="alex123432" />
   </bean>

</beans>

MyProject-security.xml

      ....
    <beans:import resource='login-service.xml'/> 
      ....

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ: поскольку все пароли, связанные с пользователем, уже зашифрованы, я должен только скрывать пароль самой базы данных DATABASE, а не таблицы. Этот пароль будет использоваться моим приложением для подключения к базе данных.

Ответы

Ответ 1

Прежде всего, вы должны знать, что независимо от того, что вы делаете, если злоумышленник получает доступ к вашим файлам сервера, он сможет украсть пароль.

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

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

Более безопасное решение - предоставить пользователю пароль (или пароль для дешифрования пароля БД) во время запуска вашего приложения, но это затруднит администрирование. И если вы уже параноик (хороший вид безопасности, а не сумасшедший), у кого-то есть доступ к вашему серверу, вы должны учитывать, что пароль БД будет находиться в системной памяти.

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

Ответ 2

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

Ответ 3

Вы можете сохранить его на сервере приложений и получить имя jndi.

Например, если вы используете какую-либо реализацию jpa, такую ​​как hibernate/eclipse-link, вы можете определить ее следующим образом

spring -security.xml

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="dataBase.db"/>
</bean>

persistence.xml

<persistence-unit name="dataBase.db" transaction-type="JTA">
...
    <jta-data-source>java:jboss/datasources/PostgresqlDS</jta-data-source>
...
</persistence-unit>

На сервере приложений вам необходимо определить связь с базой данных (datasource) в файле конфигурации сервера. В случае Jboss 7 это stadalone.xml jboss datasource.

Ответ 4

Наличие паролей в конфигурации действительно засасывает, и для нее нет серебряной пули. Однако это решение удовлетворяет большей безопасности bla-bla-bla. В верхней части также будут запутываться учетные данные в вашем SCM.

PropertyPlaceholderConfigurer:

import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

public class EncryptedPropertyPlacementConfigurer extends PropertyPlaceholderConfigurer
{
    /** algorithm used for encrpytion and decryption */
    private static final String ALGORITHM = "PBEWithMD5AndDES";

    /** 8-byte Salt. */
    private static final byte[] SALT = { ... };

    /** Iteration count. */
    private static final int ITERATION_COUNT = 19;

    /** Stores parameter specification. */
    private static final AlgorithmParameterSpec PARAM_SPEC = new PBEParameterSpec(SALT, ITERATION_COUNT);

    //All properties starting with !! will be decrypted.
    private static final String ENCRYPTIGION_LEADIN = "!!";

    public static class EncrypterException extends RuntimeException
    {
        private static final long serialVersionUID = -7336009350594115318L;

        public EncrypterException(final String message, final Throwable cause)
        {
            super(message, cause);
        }

        public EncrypterException(final String message)
        {
            super(message);
        }
    }

    private static String decrypt(final String passPhrase, final String message)
    {
        // Create the key
        final KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT, ITERATION_COUNT);
        SecretKey key;
        try
        {
            key = SecretKeyFactory.getInstance(ALGORITHM).generateSecret(keySpec);
        }
        catch (final Exception e)
        {
            throw new EncrypterException("Error setting up encryption details.", e);
        }

        if (!Base64.isBase64(message))
        {
            throw new EncrypterException("Message is not a valid base64 message.");
        }

        final String result;
        try
        {
            final Cipher cipher = Cipher.getInstance(ALGORITHM);

            cipher.init(Cipher.DECRYPT_MODE, key, PARAM_SPEC);

            final byte[] dec = Base64.decodeBase64(message);

            result = new String(cipher.doFinal(dec), "UTF-8");
        }
        catch (final Exception e)
        {
            throw new EncrypterException("Error decrypting content.", e);
        }

        return result;
    }

    @Override
    protected String convertPropertyValue(final String originalValue)
    {
        if (StringUtils.isNotBlank(originalValue) && originalValue.startsWith(ENCRYPTIGION_LEADIN))
        {
            return decrypt("<Your magic password>", originalValue.substring(2));
        }
        return super.convertPropertyValue(originalValue);
    }

}

Ваш Bean:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">


    <bean id="propertyPlaceholderConfigurer" class="...EncryptedPropertyPlacementConfigurer ">
        <property name="location" value="classpath:/spring.properties" />
        <property name="ignoreResourceNotFound" value="true" />
    </bean>

   <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">

    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.user}" />
    <property name="password" value="${jdbc.password}" />
   </bean>
</beans>

Свойство-Файл:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/muDB
jdbc.user=!!ar7CWlcL8eI=
jdbc.password=!!ar7CWlcL8eI=

Примечание: Если вы используете неограниченную политику JCE, вы также можете использовать лучший алгоритм шифрования, но поскольку мы делаем не что иное, как обфускацию, это будет делать трюк и не позволит вам завершить сеансы отладки.

Update:

Вы можете использовать это для генерации пароля:

import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import org.apache.commons.codec.binary.Base64;

public class Main
{

    private static class DesEncrypter
    {
        /** algorithm used for encrpytion and decryption */
        private static final String ALGORITHM = "PBEWithMD5AndDES";

        /** 8-byte Salt. */
        private static final byte[] SALT = { <You salt> };

        /** Iteration count. */
        private static final int ITERATION_COUNT = 19;

        /** Stores parameter specification. */
        private static final AlgorithmParameterSpec PARAM_SPEC = new PBEParameterSpec(
            SALT, ITERATION_COUNT);

        /** Key specification. */
        private final KeySpec keySpec;

        /** Secret key. */
        private final SecretKey key;

        public DesEncrypter(final String passPhrase)
        {
            // Create the key
            keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT, ITERATION_COUNT);
            try
            {
                key = SecretKeyFactory.getInstance(ALGORITHM).generateSecret(keySpec);
            }
            catch (final Exception ex)
            {
                throw new RuntimeException("Could not create DesEncrypter: " + ex.getMessage(), ex);
            }
        }

        public final String encrypt(final String message)
        {
            try
            {
                // Create cipher instance
                final Cipher cipher = Cipher.getInstance(ALGORITHM);
                // Initialize cipher
                cipher.init(Cipher.ENCRYPT_MODE, key, PARAM_SPEC);
                // Encode string
                final byte[] enc = cipher.doFinal(message.getBytes("UTF8"));
                // Encode bytes to base64 to get a string
                return Base64.encodeBase64String(enc);
            }
            catch (final Exception ex)
            {
                throw new RuntimeException("Error encrypting message.", ex);
            }
        }
    }

    public static void main(final String[] args)
    {
        if (args.length == 2)
        {
            System.out.println("!!" + new DesEncrypter(args[0]).encrypt(args[1]));
        }
    }
}

Ответ 5

вы можете сохранить в файле свойств

В моем проекте я создал базу данных .properties в META-INF в STS IDE

Ответ 6

В Rails я храню конфиденциальные данные в переменных среды в файле .env и добавляю файл в .gitignore. Я не уверен, что вы можете сделать что-то подобное.

"If I need to encrypt the password how to do it and how to find the encrypted version of password on phpMyAdmin"

Вы можете создать зашифрованный пароль через что-то вроде этого:

http://bcrypthashgenerator.apphb.com/

.. и тогда вы узнаете, что такое пароль, и вы можете добавить зашифрованную версию в правильную таблицу через phpMyadmin.

Не могли бы вы просто сохранить пароли в своем локальном репо, но не развернуть их на удаленном компьютере? Мне интересно, можно ли настроить аналогичный сценарий для Rails ENV?

Вы посмотрели на что-то вроде этого: http://www.jasypt.org/spring3.html

Ответ 7

Хорошая и старая проблема с курицей и яйцом.

Хорошо ли хранить имя пользователя и пароль базы данных в xml файл и импортировать его в файл безопасности безопасности spring?

Это лучше, чем просто хранить его в исходном коде, но хуже, чем иметь сервер приложений предприятия, обрабатывающий это для ya (например, SAP NetWeaver или Oracle WebLogic).

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

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

Есть ли лучший вариант?

Даже если вы храните учетные данные в файле, вы должны как минимум закодировать его или, если возможно, зашифровать. Но опять же, это только "обфускает" настоящий пароль.

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

Предложение 1: Сделать файл, который хранит учетные данные, доступные только для пользователя ОС и пользователя системы, а также прочитать его. Используйте шифрование секретного ключа поверх него. Лично я всегда использую алгоритм AES 256.

Предложение 2: Вместо того, чтобы хранить его в файле, попросите команду инфраструктуры (администраторов супер-ОС) отправить вам зашифрованный пароль в качестве системного параметра. Делегируйте возможность обеспечения безопасности учетных данных для команды инфраструктуры. Это текущий подход для AWS Beanstalk интеграции с RDS.

Если вы без ума от безопасности:

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

  • Возможно, вы захотите, чтобы пароль "физически" обрабатывался как внутри DVD, который должен быть вставлен на сервер с помощью член. Также вам придется обрабатывать доступ на устройстве в вашей ОС.

Не бойтесь разговаривать со своими заинтересованными сторонами об этом. Спросите его/их, что является "достаточным" приемлемым и быть счастливым об этом.

При хранении учетных данных всегда будет существовать риск.

Если мне нужно зашифровать пароль, как это сделать, и как найти зашифрованная версия пароля на phpMyAdmin? MySQL

Не копируйте свой пароль. Вы должны обрабатывать учетные данные на своем сервере.

Для одного решения мы создали специальное программное обеспечение, доступное только администраторам через протокол X11 или консоль, основанное только на Java Crypt API. Это программное обеспечение предназначено для безопасного изменения учетных данных.

Пароль всегда пересылается в безопасные SSH-соединения (если они удалены) или даже локально доступны, и только между админами и сервером, так как разрешения были определены таким образом в ОС.

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

Ответ 8

Как уже упоминалось, если вы храните пароли на сервере, вы ничего не можете сделать, если злоумышленник получает доступ к вашей машине. Единственной жизнеспособной альтернативой является использование SSL-соединения и аутентификации на основе сертификатов.

Вышеуказанный метод уже обсуждался на SO и был предоставлен ответ.

Ответ 9

Рекомендуется использовать конфигурацию Datasource на вашем сервере приложений. И попробуйте использовать это с помощью поиска JNDI, используя контекст