在配置中设置密码真的很糟糕,而且没有灵丹妙药。
但是,此解决方案符合大多数安全性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);
}
}
你的豆子:
<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 策略,您还可以使用更好的加密算法,但由于我们只做混淆处理,这将起到作用,并且不会让您以调试会话结束。
更新:
您可以使用它来生成您的密码:
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]));
}
}
}