Создание пользовательского Jasypt PropertySource в Springboot
Я использую Spring Boot для создания простого веб-приложения, которое обращается к базе данных. Я использую функциональность автоконфигурации для источника данных, настраивая spring.datasource.*
свойства в application.properties
, Это все работает блестяще и очень быстро - отличная работа, ребята @ Spring!
Моя политика компании заключается в том, что не должно быть паролей в виде открытого текста. Поэтому мне нужно иметь sping.datasource.password
зашифрованы. Немного покопавшись, я решил создать org.springframework.boot.env.PropertySourceLoader
реализация, которая создает Jasypt org.jasypt.spring31.properties.EncryptablePropertiesPropertySource
следующее:
public class EncryptedPropertySourceLoader implements PropertySourceLoader
{
private final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
public EncryptedPropertySourceLoader()
{
//TODO: this could be taken from an environment variable
this.encryptor.setPassword("password");
}
@Override
public String[] getFileExtensions()
{
return new String[]{"properties"};
}
@Override
public PropertySource<?> load(final String name, final Resource resource, final String profile) throws IOException
{
if (profile == null)
{
final Properties props = PropertiesLoaderUtils.loadProperties(resource);
if (!props.isEmpty())
{
return new EncryptablePropertiesPropertySource(name, props, this.encryptor);
}
}
return null;
}
}
Затем я упаковал это в свою банку с META-INF/spring.factories
файл следующим образом:
org.springframework.boot.env.PropertySourceLoader=com.mycompany.spring.boot.env.EncryptedPropertySourceLoader
Это отлично работает при запуске из Maven с помощью mvn spring-boot:run
, Проблема возникает, когда я запускаю ее как отдельную войну, используя java -jar my-app.war
, Приложение все еще загружается, но не удается, когда я пытаюсь подключиться к базе данных, так как значение пароля все еще зашифровано. Добавление регистрации показывает, что EncryptedPropertySourceLoader
никогда не загружается
Для меня это звучит как проблема с classpath. При запуске под maven порядок загрузки банок является строгим, но однажды под встроенным котом нет ничего, что говорило бы о том, что мой кастом jar должен быть загружен до Spring Boot.
Я попытался добавить следующее в мой pom.xml, чтобы убедиться, что classpth сохранен, но, похоже, он не имел никакого эффекта.
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifest>
<mainClass>${start-class}</mainClass>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
У кого-нибудь есть какие-либо идеи? Заранее спасибо.
ОБНОВИТЬ:
Шаг вперед: мне удалось это исправить, имея EncryptedPropertySourceLoader
реализовать класс org.springframework.core.PriorityOrdered
интерфейс и возвращение HIGHEST_PRECEDENCE
от getOrder()
, Это теперь исправило проблему неиспользованного PropertySourceLoader. Однако теперь он выдает следующую ошибку при попытке расшифровать свойства:
org.jasypt.exceptions.EncryptionInitializationException: java.security.NoSuchAlgorithmException: PBEWithMD5AndDES SecretKeyFactory not available
at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:716)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.initialize(StandardPBEStringEncryptor.java:553)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:705)
at org.jasypt.properties.PropertyValueEncryptionUtils.decrypt(PropertyValueEncryptionUtils.java:72)
at org.jasypt.properties.EncryptableProperties.decode(EncryptableProperties.java:230)
at org.jasypt.properties.EncryptableProperties.get(EncryptableProperties.java:209)
at org.springframework.core.env.MapPropertySource.getProperty(MapPropertySource.java:36)
at org.springframework.boot.env.EnumerableCompositePropertySource.getProperty(EnumerableCompositePropertySource.java:49)
at org.springframework.boot.context.config.ConfigFileApplicationListener$ConfigurationPropertySources.getProperty(ConfigFileApplicationListener.java:490)
Опять же это не происходит при запуске из mvn spring-boot:run
но происходит при запуске из исполняемого файла war. Оба сценария используют одну и ту же JVM (jdk1.6.0_35). Результаты в Google/Stackru показывают, что это проблема политики безопасности Java, но, поскольку она работает при запуске из Maven, я думаю, что могу не учитывать это. Возможно, проблема с упаковкой...
2 ответа
Здесь есть два вопроса.
1) EncryptedPropertySourceLoader должен быть загружен выше, чем стандартный PropertiesPropertySourceLoader. Это может быть достигнуто путем реализации интерфейса PriorityOrder следующим образом:
public class EncryptedPropertySourceLoader implements PropertySourceLoader, PriorityOrdered
{
private final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
public EncryptedPropertySourceLoader()
{
this.encryptor.setPassword("password"); //TODO: this could be taken from an environment variable
}
@Override
public String[] getFileExtensions()
{
return new String[]{"properties"};
}
@Override
public PropertySource<?> load(final String name, final Resource resource, final String profile) throws IOException
{
if (profile == null)
{
//load the properties
final Properties props = PropertiesLoaderUtils.loadProperties(resource);
if (!props.isEmpty())
{
//create the encryptable properties property source
return new EncryptablePropertiesPropertySource(name, props, this.encryptor);
}
}
return null;
}
@Override
public int getOrder()
{
return HIGHEST_PRECEDENCE;
}
}
org.springframework.core.io.support.SpringFactoriesLoader
класс, который загружает org.springframework.boot.env.PropertySourceLoader
от META-INF/spring.factories
упорядочивает результаты, используя org.springframework.core.OrderComparator
, Это означает, что этот класс должен быть возвращен первым, и ему будет поручено предоставить реализацию PropertySourceLoader для файлов *.proerpties.
2) Вторым является проблема загрузки класса с исполняемым JAR/WAR, которая, по-видимому, вызвана ошибкой в версии 1.1.2.RELEASE Spring Boot для Windows. Переход к версии 1.1.1.RELEASE или версии 1.1.3.RELEASE решает различные проблемы с файлом классов и свойств, которые не загружаются при запуске вне maven.
Вы можете попробовать это: jasypt-spring-boot. Он в основном оборачивает весь PropertySource, присутствующий в среде, в зашифрованную версию. 2 вещи, которые вам нужно сделать после импорта библиотеки (добавление зависимости, если вы используете maven), - аннотировать класс @Configuration с помощью @EnableEncryptableProperties и настраивать алгоритм шифрования и пароль через свойства.