自从我在这里发表上一个帖子以来已经有两个多月了,但是今年六月和七月非常忙碌而密集。 首先, Confitura的组织(欧洲最大的Java开发人员免费会议)参加了我所有的免费晚会,然后在相当紧张的住院期间,我们的第二个儿子出生了。 但是,现在,我将尝试再次定期写博客,请继续关注。
在本文中,我将简要介绍如何使用Jasypt库以一种简单,透明的方式将加密的数据存储在数据库中并检索已解密的数据。 我们的用例将是存储Twitter Api凭据,以便它们在我们的数据库中是安全的,但仍易于检索并用于在我们的时间轴中发布更新。
因此,我们有一个简单的实体来代表我们的设置项:
@Entity
public class SettingsItem implements Serializable {@Id@GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)private Integer id;private String name;private String encryptedValue;
}
在此表中,我们将存储Twitter消费者密钥,Twitter访问令牌等的值。
我们想要实现的是,当我们创建具有值作为纯文本的SettingItem对象,然后对其进行持久化时,将自动执行加密,因此在数据库中我们已对String进行了加密。 当然,当我们从数据库中检索数据时,我们希望开箱即用地看到解密的String,而无需付出额外的努力。
Jasypt进行救援
Jasypt是一个用Java编写的简单加密库。 它使开发人员免于处理低级配置细节,并使整个加密过程变得简单而直接。 而且现在最有趣的是,它还与Hibernate很好地集成在一起,可以对存储在数据库中的数据进行无缝加密/解密。
设定
要使用Jasypt及其Hibernate集成模块,我们必须在pom中添加以下两项:
<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):
@TypeDef(name="encryptedString",typeClass=EncryptedStringType.class,parameters= {// value will be used later to register encryptor@Parameter(name="encryptorRegisteredName", value="STRING_ENCRYPTOR")}
)
@Entity
public class SettingsItem implements Serializable {// (...)
}
然后在同一个类中,我们可以标记我们的ActivatedValue字段以使用此自定义类型:
@Type(type="encryptedString")private String encryptedValue;
注册加密器
我们快完成了。 我们要做的最后一件事是在HibernatePBEEncryptorRegistry类中注册加密器。 这可以在我们的应用程序的初始化类(例如ServletContext)中完成,也可以仅在具有main(String [] args)方法的类中完成:
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(),我们可以安全地配置我们的加密机制,通过在服务器计算机上设置适当的值在运行时提供密码。
摘要
作为总结,一个简短的通过测试表明我们的解决方案有效:
public class SettingsItemRepositoryShould extends IntegrationTest {@Autowiredprivate SettingsItemRepository repository;@BeforeClasspublic static void init() {StandardPBEStringEncryptor strongEncryptor = new StandardPBEStringEncryptor();strongEncryptor.setPassword("JohnDoe");HibernatePBEEncryptorRegistry registry =HibernatePBEEncryptorRegistry.getInstance();registry.registerPBEStringEncryptor("STRING_ENCRYPTOR", strongEncryptor);}@Testpublic void shouldEncryptAndDecryptValue() {// GivenString settingName = "test";String value = "EncryptMe";// Whenrepository.save(new SettingsItem(settingName, value));// ThenSettingsItem settingsItem = repository.findByName(settingName);assertThat(settingsItem.getEncryptedValue()).isEqualTo(value);}
}
翻译自: https://www.javacodegeeks.com/2013/08/transparently-persist-and-retrieve-encrypted-data-from-database.html