Прошло более двух месяцев с момента моего последнего поста, но июнь и июль были очень напряженными и напряженными месяцами в этом году. Сначала организация Confitura (крупнейшая бесплатная конференция для разработчиков Java в Европе) проводила все мои свободные вечера, а затем, после довольно нервного периода в больнице, родился наш второй сын. Но теперь я снова попытаюсь вести блог, поэтому, пожалуйста, следите за обновлениями.
В этой статье я кратко опишу, как мы можем хранить зашифрованные данные в нашей базе данных и извлекать их, как уже расшифровано, простым и прозрачным способом с использованием библиотеки Jasypt . В нашем случае мы будем хранить учетные данные Twitter Api, чтобы они были в безопасности в нашей базе данных, но при этом их было легко найти и использовать для публикации обновлений в нашей временной шкале.
Итак, у нас есть простая сущность, представляющая наш элемент настроек:
|
01
02
03
04
05
06
07
08
09
10
|
@Entitypublic class SettingsItem implements Serializable { @Id @GeneratedValue(strategy = javax.persistence.GenerationType.AUTO) private Integer id; private String name; private String encryptedValue;} |
В такой таблице мы будем хранить значения для ключа потребителя Twitter, токена доступа Twitter и так далее.
Чего мы хотели бы достичь, так это того, что когда мы создаем объект SettingItem со значением в виде простого текста, а затем сохраняем его, шифрование выполняется автоматически, поэтому в БД мы зашифровали строку. И, конечно же, когда мы получаем данные из БД, мы хотим увидеть расшифрованную строку без дополнительных усилий, просто из коробки.
Джасып на помощь
Jasypt — это простая библиотека шифрования, написанная на Java. Это освобождает разработчика от необходимости работать с деталями конфигурации низкого уровня и делает весь процесс шифрования простым и понятным. И что самое интересное сейчас, у него также есть хорошая интеграция с Hibernate, позволяющая бесшовное шифрование / дешифрование данных, хранящихся в базе данных.
Настроить
Чтобы использовать Jasypt и его модуль интеграции Hibernate, мы должны добавить два элемента в наш pom:
|
01
02
03
04
05
06
07
08
09
10
|
<dependency> <groupId>org.jasypt</groupId> <artifactId>jasypt</artifactId> <version>1.9.0</version> </dependency> <dependency> <groupId>org.jasypt</groupId> <artifactId>jasypt-hibernate4</artifactId> <version>1.9.0</version> </dependency> |
Пользовательский тип
Затем мы должны объявить пользовательский тип Hibernate (@TypeDef) в нашей сущности:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
@TypeDef( name="encryptedString", typeClass=EncryptedStringType.class, parameters= { // value will be used later to register encryptor @Parameter(name="encryptorRegisteredName", value="STRING_ENCRYPTOR") })@Entitypublic class SettingsItem implements Serializable { // (...)} |
и после этого в том же классе мы можем пометить наше поле encryptedValue для использования этого пользовательского типа:
|
1
2
|
@Type(type="encryptedString") private String encryptedValue; |
Регистрация шифратора
Мы почти закончили. Последнее, что нам нужно сделать, это зарегистрировать шифровальщик в классе HibernatePBEEncryptorRegistry. Это можно сделать в классе инициализации нашего приложения, например, ServletContext или просто в классе с методом main (String [] args):
|
1
2
3
4
5
6
7
|
String password = System.getProperty("jasypt.password"); StandardPBEStringEncryptor strongEncryptor = new StandardPBEStringEncryptor(); strongEncryptor.setPassword(password); HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); registry.registerPBEStringEncryptor("STRING_ENCRYPTOR", strongEncryptor); |
Здесь важно то, что с помощью System.getProperty () или System.getenv () мы можем безопасно настроить наш механизм шифрования, пароль предоставляется во время выполнения, устанавливая правильное значение на сервере.
Резюме
В качестве резюме, один короткий проходной тест, показывающий, что наше решение работает:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public class SettingsItemRepositoryShould extends IntegrationTest { @Autowired private SettingsItemRepository repository; @BeforeClass public static void init() { StandardPBEStringEncryptor strongEncryptor = new StandardPBEStringEncryptor(); strongEncryptor.setPassword("JohnDoe"); HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); registry.registerPBEStringEncryptor("STRING_ENCRYPTOR", strongEncryptor); } @Test public void shouldEncryptAndDecryptValue() { // Given String settingName = "test"; String value = "EncryptMe"; // When repository.save(new SettingsItem(settingName, value)); // Then SettingsItem settingsItem = repository.findByName(settingName); assertThat(settingsItem.getEncryptedValue()).isEqualTo(value); }} |
