jpa加密_使用JPA侦听器的数据库加密

jpa加密

最近,我不得不将数据库加密添加到一些字段中,并且发现了很多不好的建议。

建筑问题

最大的问题是建筑。 如果持久性管理器静静地处理您的加密,那么根据定义,您的体系结构将在持久性和安全性设计之间要求紧密而不必要的绑定。 您不能触摸一个而不接触另一个。

这似乎是不可避免的,但是有一个受人尊敬的想法,那就是最好的架构是您拥有独立的应用程序开发人员和安全开发人员团队的架构。 应用程序开发人员不能草率,但总的来说,他们唯一的重点是功能完成。 安全开发人员负责设计和实现安全性。 唯一考虑这两个方面的地方是建筑和顶层设计。

过去这不是很实用,但是面向方面的编程(AOP)和类似的概念已经改变了这一点。 现在,在服务层和持久层之间注入一个拦截器是完全合理的,这样,无权允许调用者看到的值被悄悄地丢弃了。 10个项目的列表可能会减少到7个,或者更新可能会引发异常,而不是修改只读值。 当持久化集合时,它要复杂一些,但是一般方法应该很清楚。

这里的关键是,应用程序开发人员无需查看安全代码。 所有这些都可以通过在部署时通过配置文件添加的AOP注入来处理。 更重要的是,它可以随时更改,而无需修改应用程序本身。 (您可能需要执行一个更新过程,该过程将更改数据库中的值。)

拦截器甚至可以阻止对未记录方法的调用-减少了对流氓程序员的担心。

在实践中,许多站点将有几个开发人员都戴上帽子,而不是拥有专门的安全团队。 只要他们能够牢记自己的职责,这不是问题。

在JPA或Hibernate字段中进行透明加密绝对比在POJO中放入加密/解密代码更好,但是它仍然在安全性和持久性层之间强加了不必要的绑定。 它还存在严重的安全问题。

安全问题

每当您要处理加密时,都会遇到一个关键问题–可以将此对象写入磁盘吗? 最明显的威胁是序列化,例如,通过钝化数据以释放内存或将其迁移到其他服务器的应用服务器。

实际上,这意味着您的密钥和纯文本内容必须标记为“ transient”(对于序列化引擎)和“ @Transient”(对于JPA或Hibernate)。 如果您真的很疑惑,您甚至会覆盖隐式序列化方法writeObject,因此可以绝对保证这些字段永远不会写入磁盘。

这是可行的……但是它使透明的加密/解密大为失败,因为该代码的全部目的是使这些字段看起来就像另一个字段。 您必须维护两个字段-持久加密值和瞬态未加密值-并具有某种使它们保持同步的方法。 无需在您的pojo中放入任何密码即可完成所有操作。

一个更微妙的问题是,如果攻击者可以通过使应用服务器崩溃而触发核心转储,则您的对象仍可能写入磁盘。 细心的站点管理员将禁用核心转储,但许多人忽略了它。 解决这个问题比较困难,但是如果AOP可以在需要解密值的方法周围立即解密/加密值,则有可能。 您的应用程序不关心解密在哪里发生,只要它在需要时进行解密即可。 这是应该留给安全团队的决策类型。

可以将对象写入磁盘的第三种方法是通过OS交换文件,但这应该不是问题,因为交换文件现在通常已加密。

JPA实体侦听器

一个解决方案是JPA EntityListeners或相应的Hibernate类。 这些是侦听器类,可以提供在数据库对象创建,删除或修改之前或之后调用的方法。

样例代码

使用一些示例代码最容易看到这一点。 考虑一种情况,我们必须保留第三方站点的用户密码。 在这种情况下,我们必须使用加密,而不是哈希。

(注意:我怀疑这是Twitter第三方应用程序所需的实际信息–仅用于说明目的。)

实体

/*** Conventional POJO. Following other conventions the sensitive* information is written to a secondary table in addition to being* encrypted.*/
@Entity
@Table(name='twitter')
@SecondaryTable(name='twitter_pw', pkJoinColumns=@PrimaryKeyJoinColumn(name='twitter_id'))
@EntityListeners(TwitterUserPasswordListener.class)
public class TwitterUser {private Integer id;private String twitterUserprivate String encryptedPassword;transient private String password;@Id@GeneratedValue(strategy = GenerationType.IDENTITY)public Integer getId() { return id; }@Column(name = 'twitter_user')public String getTwitterUser() { return twitterUser; }@Column(name = 'twitter_pw', table = 'twitter_pw')@Lobpublic String getEncryptedPassword() { return encryptedPassword; }@Transientpublic String getPassword() { return password; }// similar definitions for setters....
}


DAO

/*** Conventional DAO to access login information.*/
@LocalBean
@Stateless
public class TwitterDao {@PersistenceContextprivate EntityManager em;/*** Read an object from the database.*/@TransactionAttribute(TransactionAttributeType.SUPPORTS)public TwitterUser getUserById(Integer id) {return em.find(TwitterUser.class, id);}/*** Create a new record in the database.*/@TransactionAttribute(TransactionAttributeType.REQUIRED)public saveTwitterUser(TwitterUser user) {em.persist(user);}/*** Update an existing record in the database.** Note: this method uses JPA semantics. The Hibernate* saveOrUpdate() method uses slightly different semantics* but the required changes are straightforward.*/@TransactionAttribute(TransactionAttributeType.REQUIRED)public updateTwitterUser(TwitterUser user) {TwitterUser tw = em.merge(user);// we need to make one change from the standard method -// during a 'merge' the old data read from the database// will result in the decrypted value overwriting the new// plaintext value - changes won't be persisted! This isn't// a problem when the object is eventually evicted from// the JPA/Hibernate cache so we're fine as long as we// explicitly copy any fields that are hit by the listener.tw.setPassword(user.getPassword());return tw;}


EntityListener

为了在持久层和安全层之间保持清晰的隔离,侦听器不执行任何操作,而是调用处理加密的服务。 它完全不了解加密细节。

public class TwitterUserPasswordListener {@Injectprivate EncryptorBean encryptor;/*** Decrypt password after loading.*/@PostLoad@PostUpdatepublic void decryptPassword(Object pc) {if (!(pc instanceof TwitterUser)) {return;}TwitterUser user = (TwitterUser) pc;user.setPassword(null);if (user.getEncryptedPassword() != null) {user.setPassword(encryptor.decryptString(user.getEncryptedPassword());}}/*** Decrypt password before persisting*/@PrePersist@PreUpdatepublic void encryptPassword(Object pc) {if (!(pc instanceof TwitterUser)) {return;}TwitterUser user = (TwitterUser) pc;user.setEncryptedPassword(null);if (user.getPassword() != null) {user.setEncryptedPassword(encryptor.encryptString(user.getPassword());}}
}


EncryptorBean

EncryptorBean处理加密,但不知道正在加密什么。 这是一个最小的实现–在实践中,我们可能会希望除了密文/明文之外还传递一个keyId。 这将使我们能够以最小的干扰安静地旋转加密密钥-这是通常的“简单加密”方法绝对不可能实现的。

此类使用OWASP / ESAPI进行加密,因为1)它应已由您的应用程序使用; 2)可移植格式允许其他应用程序使用我们的数据库,只要它们也使用OWASP / ESAPI库即可。

该实现仅涵盖字符串–健壮的解决方案应具有针对所有原始类型以及可能针对特定领域的类(例如信用卡)的方法。

import org.owasp.esapi.ESAPI;
import org.owasp.esapi.Encryptor;
import org.owasp.esapi.codecs.Base64;
import org.owasp.esapi.crypto.CipherText;
import org.owasp.esapi.crypto.PlainText;
import org.owasp.esapi.errors.EncryptionException;
import org.owasp.esapi.reference.crypto.JavaEncryptor;@Stateless
public class EncryptorBean {private static final String PBE_ALGORITHM = 'PBEWITHSHA256AND128BITAES-CBC-BC';private static final String ALGORITHM = 'AES';// hardcoded for demonstration use. In production you might get the// salt from the filesystem and the password from a appserver JNDI value.private static final String SALT = 'WR9bdtN3tMHg75PDK9PoIQ==';private static final char[] PASSWORD = 'password'.toCharArray();// the keyprivate transient SecretKey key;/*** Constructor creates secret key. In production we may want* to avoid keeping the secret key hanging around in memory for* very long.*/public EncryptorBean() {try {// create the PBE keyKeySpec spec = new PBEKeySpec(PASSWORD, Base64.decode(SALT), 1024);SecretKey skey = SecretKeyFactory.getInstance(PBE_ALGORITHM).generateSecret(spec);// recast key as straightforward AES without padding.key = new SecretKeySpec(skey.getEncoded(), ALGORITHM);} catch (SecurityException ex) {// handle appropriately...}}/*** Decrypt String*/public String decryptString(String ciphertext) {String plaintext = null;if (ciphertext != null) {try {Encryptor encryptor = JavaEncryptor.getInstance();CipherText ct = CipherText.from PortableSerializedBytes(Base64.decode(ciphertext));plaintext = encryptor.decrypt(key, ct).toString();} catch (EncryptionException e) {// handle exception. Perhaps set value to null?}}return plaintext;}/*** Encrypt String*/public String encryptString(String plaintext) {String ciphertext= null;if (plaintext!= null) {try {Encryptor encryptor = JavaEncryptor.getInstance();CipherText ct = encryptor.encrypt(key, new PlaintText(plaintext));ciphertext = Base64.encodeBytes(ct.asPortableSerializedByteArray());} catch (EncryptionException e) {// handle exception. Perhaps set value to null?}}return ciphertext;}
}


最后的想法

没有理由为什么未加密字段和加密字段之间必须具有一对一的关系。 将相关字段捆绑为一个值是完全合理的-实际上,最好单独加密每个字段。 这些值可以用CSV,XML,JSON甚至属性文件表示。

参考: Invariant Properties博客中的JCG合作伙伴 Bear Giles 使用JPA侦听器进行数据库加密 。

翻译自: https://www.javacodegeeks.com/2012/11/database-encryption-using-jpa-listeners.html

jpa加密

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351792.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

同一进程中的线程究竟共享哪些资源

线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID。 进程拥有这许多共性的同时,还拥有自己的个性。有了这些…

物联lot是什么意思_什么是物联网,物联网(lOT)简介

什么是物联网物联网(The Internet of Things,简称IOT)是指通过各种信息传感器、射频识别技术、全球定位系统、红外线感应器、激光扫描器等各种装置与技术,实时采集任何需要监控、 连接、互动的物体或过程,采集其声、光、热、电、力学、化 学、…

Python 位操作运算符

&按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0(a & b) 输出结果 12 ,二进制解释: 0000 1100|按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。(a | b) 输出结果 6…

JavaOne 2016后续活动

我很高兴今年参加了JavaOne,我可以用一个词概括一下这一经验:Brilliant。 对于我来说,今年与往年相比有很大不同,因为我在周日有一个演讲要共同演讲,而我剩下的一周时间都可以参加会议。 因此,我了解到在Ja…

python对初学者的看法_python学习之道(1)——新手小白对print()函数的理解,Python,之路,一,浅谈...

Python学习之路(一) ——浅谈新手小白对print()函数的理解写在前面笔者目前为在校大四学生(某末流211),大学生活即将画上终点,然而却还没有真正精通一门语言,很是惭愧。在大学期间参加了各种文体活动,获得了很多次演讲比赛的奖项&…

理解Windows内核模式与用户模式

1、基础 运行 Windows 的计算机中的处理器有两个不同模式:“用户模式”和“内核模式”。根据处理器上运行的代码的类型,处理器在两个模式之间切换。应用程序在用户模式下运行,核心操作系统组件在内核模式下运行。多个…

判断使用设备是PC还是phone

<script type"text/javascript"> //如果是手机设备&#xff0c;则.. if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {window.location.href "http://www."; } </script><style type"text/css"> me…

求1+2+3+...+n

题目描述 求123...n&#xff0c;要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句&#xff08;A?B:C&#xff09;。 1、根据基本公式展开&#xff0c;利用java的幂函数代替乘法&#xff0c;利用位移运算代替除法 public class Solution {pub…

1 京东_推荐好友拿好礼 | 每1积分可兑换30元京东电子卡

三季度转推介活动火热进行中该积分最终以被推荐客户9月30日金融资产余额为依据积分兑现时间为活动结束后15个工作日我行会将京东电子卡密码通过短信方式直接发送至推荐客户预留手机号码上(请推荐客户登记真实、准确的电话号码&#xff0c;否则无法兑现积分奖励)尊敬的客户&…

在cmd命令行下编译运行C/C++源文件

一直用java来写程序&#xff0c;java配置好jre路径之后&#xff0c;在cmd下编译运行&#xff0c;很方便。 刚好要给一个舍友改下C程序&#xff0c;想到可不可以像java一样在环境变量里配置好C的编译路径呢&#xff1f; 于是上网搜了一下&#xff0c;得到如下结果&#xff1a; 一…

制作程序化装饰花纹图案_用装饰器设计图案装饰

制作程序化装饰花纹图案装饰图案是广泛使用的结构图案之一。 此模式在运行时动态更改对象的功能&#xff0c;而不会影响对象的现有功能。 简而言之&#xff0c;此模式通过包装将附加功能添加到对象。 问题陈述&#xff1a; 想象一个场景&#xff0c;我们有一个比萨饼&#xff…

10停止nginx命令 win_windows版nginx快速操控神器(重启,关闭)

众所周知,Windows 版本的Nginx 是linux版本的阉割版,但是在开发或者个人测试的时候,还是非常好用的&#xff0c;但是nginx运行的命令自己敲打起来不是那么的方便,因此呢&#xff0c;我们就写了个Bat批处理小程序&#xff0c;封装了这些命令&#xff0c;2.1版本您只需要配置下 N…

学习vi和vim编辑器(8):全局替换(1)

本章学习vi编辑器中的全局替换命令。通过全局替换命令&#xff0c;可以自动替换文件中所有出现过的某个单词。全局替换一般会用到两个ex命令&#xff1a;":g"(global)&#xff0c;":s"(substitute)。 替换命令&#xff1a; 替换命令的语法如下&#xff1…

使用DynamoDBMapper查询DynamoDB项目

在上一篇文章中&#xff0c;我们使用底层Java api在DynamoDB数据库上发出了查询。 使用DynamoDBMapper进行查询非常简单。 使用哈希键发出查询非常简单。 这样的查询的最佳候选者是通过使用电子邮件哈希键进行搜索的Users表。 public User getUser(String email) {User user…

实训二—博客三

学期末总结 经过了一个学期的java学习&#xff0c;使我对java产生了很大的兴趣&#xff0c;虽然我学的并不怎么好&#xff0c;但是我喜欢程序可以成功运行时带来的成就感&#xff0c;我也享受排错的过程。学加练的上课模式我觉得也很棒&#xff0c;给了我们独立思考编程的时间&…

小肚皮最新版本_小肚皮旧版本

00后最炙手可热的社交软件《小肚皮旧版本》等你下载天&#xff0c;在这里独特的社交玩法等你感受&#xff0c;为你带来有趣的玩法乐趣&#xff0c;小肚皮旧版本中丰富的乐趣玩法等你来感受&#xff0c;让你轻松享受到更多的乐趣所在&#xff0c;为你带来不一样的社交乐趣。特色…

小心使用STL中map的[]操作符

一个map就是一个&#xff08;关键码&#xff08;key&#xff09;&#xff0c;值&#xff08;value&#xff09;&#xff09;对偶的序列&#xff0c;它提供基于关键码的快速提取操作。也就是说&#xff0c;可以用下标运算符[]将关键码作为下标去执行查找&#xff0c;并返回对应的…

存图

转载于:https://www.cnblogs.com/simple-huang/p/10183360.html

地平线机器人_地平线机器人CEO余凯:基于深度学习的自动驾驶之路

请关注公众号“汽车创新港”&#xff0c;获取后续更多论坛实录&#xff01;加工作人员微信号&#xff1a;tinydanio&#xff0c;备注“我要入群”直接进入直播群&#xff01;今天都是大牛&#xff0c;下面的也是技术大牛&#xff0c;是百度深度学习实验室创始人&#xff0c;百度…

Mac os下android studio模拟器无法联网解决方法

步骤1: https://blog.csdn.net/qq_33945246/article/details/79908298 步骤2: 访达进入/Users/文件夹 步骤3: shiftcmmand.显示隐藏文件夹 步骤4 打开.android文件夹 点击adv文件夹进入&#xff0c;然后回到 "步骤1"查看解决方法 本人创业做的一款androidApp, 下载量…