几天前,我读了Bear Giles关于2012年使用JPA监听器进行数据库加密的有趣文章。他讨论了对加密解决方案的要求,并提供了JPA监听器的代码示例。 他的主要要求是:

  • 提供不影响应用程序的透明加密,
  • 能够在部署时添加加密,
  • 由两个不同的团队/人员开发应用程序和安全性/加密。

我完全同意他的看法。 但是,经过1.5年的时间和对JPA 2.1的规范更新,JPA侦听器不再是唯一的解决方案。 JPA 2.1引入了类型转换器,可用于创建可能更好的解决方案。

一般信息和设置

该示例期望您具有有关JPA类型转换器的一些基本知识。 如果您想更详细地了解类型转换器,请查看我以前关于JPA 2.1 –如何实现类型转换器的文章 。

以下示例的设置很小。 您只需要与Java EE 7兼容的应用程序服务器。 我用Wildfly 8.0.0.Final包含休眠4.3.2.Final作为JPA实现。

创建CryptoConverter

付款信息(如信用卡号)是应加密的机密信息。 以下代码片段显示了我们将在此示例中使用的CreditCard实体。

@Entity
public class CreditCard {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;private String ccNumber;private String name;...
}

正如我们一开始所指出的,加密应该以透明的方式进行。 这意味着该应用程序不受加密影响,并且可以在不更改现有代码库的情况下对其进行添加。 对我来说,这还包括数据库中的数据模型,因为它通常是由某些应更改的应用程序特定脚本创建的。 因此,我们需要一个类型转换器,在加密和解密信息时不更改数据类型。

下面的代码片段显示了这种转换器的示例。 如您所见,转换器非常简单。 在将实体持久存储到数据库之前,hibernate会调用convertToDatabaseColumn方法。 它从实体获取未加密的字符串,并使用带有PKCS5Padding的AES算法进行加密。 然后,使用base64编码将加密的byte []转换为字符串 ,该字符串将保留在数据库中。

当持久性提供程序从数据库读取实体时,将调用convertToEntityAttribute方法。 它从数据库中获取加密的String ,使用base64解码将其转换为byte []并执行解密。 解密后的字符串将分配给实体的属性。

对于真实的应用程序,您可能需要花费更多的精力进行加密或将其移至单独的类。 但这足以说明一般想法。

@Converter
public class CryptoConverter implements AttributeConverter<String, String> {private static final String ALGORITHM = "AES/ECB/PKCS5Padding";private static final byte[] KEY = "MySuperSecretKey".getBytes();@Overridepublic String convertToDatabaseColumn(String ccNumber) {// do some encryptionKey key = new SecretKeySpec(KEY, "AES");try {Cipher c = Cipher.getInstance(ALGORITHM);c.init(Cipher.ENCRYPT_MODE, key);return Base64.encodeBytes(c.doFinal(ccNumber.getBytes()));} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic String convertToEntityAttribute(String dbData) {// do some decryptionKey key = new SecretKeySpec(KEY, "AES");try {Cipher c = Cipher.getInstance(ALGORITHM);c.init(Cipher.DECRYPT_MODE, key);return new String(c.doFinal(Base64.decode(dbData)));} catch (Exception e) {throw new RuntimeException(e);}}
}

好的,我们有一个类型转换器,可以对字符串进行加密和解密。 现在,我们需要告诉休眠模式使用该转换器来保留CreditCard实体的ccNumber属性。 如前一篇文章中所述 ,我们可以使用@Convert注释。 但这将更改我们应用程序的代码。

另一个也是我们的要求,更好的选择是在XML配置中分配转换器。 这可以在orm.xml文件中完成。 以下代码段将CryptoConverter分配给CreditCard实体的ccNumber属性。

<entity-mappings version="2.1"xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"><entity class="blog.thoughts.on.java.jpa21.enc.entity.CreditCard"><convert converter="blog.thoughts.on.java.jpa21.enc.converter.CryptoConverter" attribute-name="ccNumber"/></entity>
</entity-mappings>

这就是我们为单个数据库字段实现和配置基于类型转换器的加密所需要做的一切。

实体侦听器还是类型转换器?

这个问题的答案并不像看起来那样容易。 两种解决方案都有其优点和缺点。

Bear Giles描述的实体侦听器可以在加密过程中使用实体的多个属性。 因此,您可以加入多个属性,对其进行加密,然后将加密的数据存储在一个数据库字段中。 或者,您可以对加密和解密的数据使用不同的属性,以避免对解密的数据进行序列化( 如Bear Giles所述 )。 但是使用实体侦听器也有缺点。 它的实现特定于实体,并且比类型转换器的实现复杂。 而且,如果需要加密其他属性,则需要更改实现。

如您在上面的示例中所看到的,类型转换器的实现既简单又可重用。 CryptoConverter可以用于加密任何实体的任何String属性。 并且通过使用基于XML的配置将转换器注册到实体属性,它不需要更改应用程序的源代码。 如果迁移现有数据,您甚至可以在以后的某个时间将其添加到应用程序中。 该解决方案的缺点是,加密的实体属性不能标记为瞬态。 如果将实体写入磁盘,则可能会导致漏洞。

您会看到,两种方法都有其优缺点。 您必须决定哪些优点和缺点对您来说更重要。

结论

在本文的开头,我们定义了3个要求:

  • 提供不影响应用程序的透明加密,
  • 能够在部署时添加加密,
  • 由两个不同的团队/人员开发应用程序和安全性/加密。

所描述的CryptoConverter实现实现了所有这些。 如果使用XML配置分配类型转换器,则可以在部署时添加加密,并且不会影响应用程序。 应用程序的开发和加密是完全独立的,可以由不同的团队来完成。 最重要的是,CryptoConverter可用于转换任何实体的任何String属性。 因此具有很高的可重用性。 但是,正如我们在上一段中看到的那样,此解决方案也存在一些缺点。

您必须决定要使用哪种方法。 请给我评论您的选择。

翻译自: https://www.javacodegeeks.com/2014/06/how-to-use-a-jpa-type-converter-to-encrypt-your-data.html

如何使用JPA Type Converter加密数据相关推荐

  1. LLBL Gen 3.x 源代码追踪与解析 Type Converter 类型转换器

    TypeConverter 类,MSDN中的解释是提供一种将值的类型转换为其他类型以及访问标准值和子属性的统一方法. 先看一下例子,能够将字符串翻译成点结构的类型转换器 public class Po ...

  2. jpa 返回数据转换_如何使用JPA类型转换器加密数据

    jpa 返回数据转换 几天前,我读了Bear Giles关于2012年使用JPA监听器进行数据库加密的有趣文章.他讨论了对加密解决方案的要求,并提供了JPA监听器的代码示例. 他的主要要求是: 提供不 ...

  3. XAML实例教程系列 - 类型转换器(Type Converter)

    在XAML中每一个对象元素映射一个实例,而实例属性可以通过特性(Attributes)进行赋值.在实际项目开发中,对象元素的属性值可以是不同数据类型,根据需求不同,经常需要对数据类型进行转换,就需要使 ...

  4. jpa 测试_使用外星人进行测试:如何使用Arquillian测试JPA类型转换器

    jpa 测试 该帖子与+ Aslak Knutsen ( @aslakknutsen )一起撰写. JPA类型转换器为定义实体属性如何持久存储到数据库提供了一种简便的方法. 您可以使用它们来实现许多不 ...

  5. 使用外星人进行测试:如何使用Arquillian测试JPA类型转换器

    该帖子与+ Aslak Knutsen ( @aslakknutsen )一起撰写. JPA类型转换器为定义实体属性如何持久存储到数据库提供了一种简便的方法. 您可以使用它们来实现许多不同的功能,例如 ...

  6. JPA 2.1类型转换器–保留枚举的更好方法

    可以使用JPA 2.0保留枚举,但是没有很好的方法来实现. 使用@Enumerated批注,可以使用EnumType.ORDINAL或EnumType.STRING将枚举值映射到其数据库表示形式. 但 ...

  7. 1.0jpa 2.0_JPA 2.1类型转换器–持久枚举的更好方法

    1.0jpa 2.0 可以使用JPA 2.0保留枚举,但是没有很好的方法来实现. 使用@Enumerated批注,可以使用EnumType.ORDINAL或EnumType.STRING将枚举值映射到 ...

  8. JPA 菜鸟教程 18 自动把firstName+lastName合并为name字段

    GitHub src="//ghbtns.com/github-btn.html?user=je-ge&repo=jpa&type=watch&count=true& ...

  9. 领域驱动设计战术模式--值对象

    值对象虽然经常被掩盖在实体的阴影之下,但它却是非常重要的 DDD 概念. 值对象不具有身份,它纯粹用于描述实体的特性.处理不具有身份的值对象是很容易的,尤其是不变性与可组合性是支持易用性的两个特征. ...

最新文章

  1. linux 查看进程端口_如何简单有效的查看windows进程使用了哪些端口
  2. 算法提高 学霸的迷宫
  3. 【过程记录】springboot中使用EhcacheCache+mybatis
  4. tomcat高并发配置
  5. Ubuntu安装配置Mysql
  6. jzoj4025-找回密码【后缀自动机】
  7. Fiddler使用过程中容易忽略的小技巧
  8. 【干货】卷积神经网络Alex-Net、VGG-Nets、Network-In-Network案例分析
  9. Ubuntu创建python虚拟环境
  10. @程序员,物联网软件开发不得不克服的七大挑战
  11. #ifdef __cplusplus extern C { #endif”的定义
  12. 基于FPGA的SDRAM控制器设计(4)
  13. TurboMail邮件系统配置之预防邮件炸弹
  14. iOS绘制1像素的线
  15. sem_wait和sem_post
  16. LeetCode岛屿的最大面积
  17. 阿里云服务器企业用户最新配置表!
  18. python极简应用_30 个极简Python代码,拿走即用(真干货)
  19. Firemonkey arm-linux-androideabi-ld.exe: previous definition here
  20. 《百家讲坛》很难再火了

热门文章

  1. 堆排序原理及其实现(C++)
  2. git 在ssh情况下提交代码
  3. c语言关于计算的函数,问个c语言题目,关于一个计算器的有参有返回函数!!!...
  4. linux下单点故障的软件,KeepAlived防止单点故障
  5. mysql duplicate key与replace into对比
  6. 这七种回归分析技术,学了不后悔
  7. apache.camel_Apache Camel 3.1 –即将推出更多骆驼核心优化
  8. spring mvc教程_Spring MVC教程
  9. java面试spring_针对Java程序员的二十大Spring REST面试问题答案
  10. maven 生成本地库_在2017年从Maven工件生成P2存储库