我应该在哪里保留数据库的凭据?

Jac*_*ack 22 java mysql tomcat spring-security

将数据库的用户名和密码保存在xml文件中并将其导入spring security的安全文件中是一个好主意吗?还有更好的选择吗?如果我需要加密密码怎么做以及如何在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>
Run Code Online (Sandbox Code Playgroud)

MyProject的-security.xml文件

      ....
    <beans:import resource='login-service.xml'/> 
      ....
Run Code Online (Sandbox Code Playgroud)

请注意:由于所有用户相关的密码都已加密,我只想隐藏DATABASE本身的密码而不是表格列.我的应用程序将使用此密码连接到数据库.

jec*_*nom 31

首先,您应该知道,无论您做什么,如果攻击者获得对您的服务器文件的访问权限,他将能够窃取密码.

如果您使用应用服务器的数据源,则只需将明文密码的位置移动到其他文件即可.

如果您使用某种形式的加密来避免存储明文密码,那么您的应用仍然需要使用其已有的另一个密码对其进行解密.如果攻击者竭尽全力访问您的系统,您可以相信他也会知道这一点.你正在做的是混淆(并获得虚假的安全感)而不是实际保护它.

更安全的解决方案是让用户在应用启动期间提供密码(或密码来解密数据库密码),但这会使管理变得非常困难.如果你已经是偏执狂(安全性很好,而不是那种疯狂的那种)有人可以访问你的服务器,你应该考虑到DB密码将驻留在系统内存中.

除此之外,请将密码保存在配置文件中(您可以相当确信服务器不会向外界显示),锁定系统并仅为数据库用户提供所需的最低权限.

  • *唯一安全的解决方案是让用户在应用启动期间提供密码(或密码来解密数据库密码),但这会使管理变得非常困难.*==> false,如果您有权访问系统,内存快照对于java来说是微不足道的. (3认同)
  • 很多人假设数据库与应用程序位于同一服务器上,并且它只保存该应用程序的数据...是否曾与购买大型 Oracle 安装的公司合作过?考虑到这样的密码将被签入并分发到 N 个开发人员桌面,因此破解一个开发桌面,您就可以获得与数据库通信的凭据,而无需破解应用程序服务器。没关系,人们可能想在开发/质量保证/生产环境中运行应用程序,这些环境应该有不同的密码,也可能有不同的用户。 (3认同)
  • 非常感谢,但是配置文件是什么意思?你能给我举个例子吗 (2认同)
  • 它是应用程序内存内容的转储。你可以分析它来找到每个变量的值。请参阅此处:http://docs.oracle.com/javase/6/docs/technotes/tools/share/jmap.html (2认同)

geo*_*and 7

一种选择是使用Jasypt与它的Spring集成,以便能够将用户名/密码作为属性存储在常规属性文件中,但是以加密形式存储.Jasypt将透明地处理解密

  • 但我们仍然需要提供密钥来解密,我们将该密钥存储在哪里? (5认同)

Han*_*nes 5

配置密码真的很糟糕,并没有银弹.然而,这种解决方案适用于大多数安全性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);
    }

}
Run Code Online (Sandbox Code Playgroud)

你的豆子:

<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>
Run Code Online (Sandbox Code Playgroud)

你的财产档案:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/muDB
jdbc.user=!!ar7CWlcL8eI=
jdbc.password=!!ar7CWlcL8eI=
Run Code Online (Sandbox Code Playgroud)

注意: 如果您使用无限制的JCE策略,您也可以使用更好的加密算法,但由于我们除了混淆之外什么也没做,这样做就可以了,并且不会让您最终得到调试会话.

更新:

您可以使用它来生成密码:

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]));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Spr*_*ner 1

您可以保留在属性文件中

在我的项目中,我在 STS IDE 的 META-INF 下创建了一个database.properties