如何使用JPA Type Converter加密数据
幾天前,我讀了Bear Giles關(guān)于2012年使用JPA監(jiān)聽(tīng)器進(jìn)行數(shù)據(jù)庫(kù)加密的有趣文章。他討論了對(duì)加密解決方案的要求,并提供了JPA監(jiān)聽(tīng)器的代碼示例。 他的主要要求是:
- 提供不影響應(yīng)用程序的透明加密,
- 能夠在部署時(shí)添加加密,
- 由兩個(gè)不同的團(tuán)隊(duì)/人員開(kāi)發(fā)應(yīng)用程序和安全性/加密。
我完全同意他的看法。 但是,經(jīng)過(guò)1.5年的時(shí)間和對(duì)JPA 2.1的規(guī)范更新,JPA偵聽(tīng)器不再是唯一的解決方案。 JPA 2.1引入了類(lèi)型轉(zhuǎn)換器,可用于創(chuàng)建可能更好的解決方案。
一般信息和設(shè)置
該示例期望您具有有關(guān)JPA類(lèi)型轉(zhuǎn)換器的一些基本知識(shí)。 如果您想更詳細(xì)地了解類(lèi)型轉(zhuǎn)換器,請(qǐng)查看我以前關(guān)于JPA 2.1 –如何實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器的文章 。
以下示例的設(shè)置很小。 您只需要與Java EE 7兼容的應(yīng)用程序服務(wù)器。 我用Wildfly 8.0.0.Final包含休眠4.3.2.Final作為JPA實(shí)現(xiàn)。
創(chuàng)建CryptoConverter
付款信息(如信用卡號(hào))是應(yīng)加密的機(jī)密信息。 以下代碼片段顯示了我們將在此示例中使用的CreditCard實(shí)體。
@Entity public class CreditCard {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;private String ccNumber;private String name;... }正如我們一開(kāi)始所指出的,加密應(yīng)該以透明的方式進(jìn)行。 這意味著該應(yīng)用程序不受加密影響,并且可以在不更改現(xiàn)有代碼庫(kù)的情況下對(duì)其進(jìn)行添加。 對(duì)我來(lái)說(shuō),這還包括數(shù)據(jù)庫(kù)中的數(shù)據(jù)模型,因?yàn)樗ǔJ怯赡承?yīng)更改的應(yīng)用程序特定腳本創(chuàng)建的。 因此,我們需要一個(gè)類(lèi)型轉(zhuǎn)換器,在加密和解密信息時(shí)不更改數(shù)據(jù)類(lèi)型。
下面的代碼片段顯示了這種轉(zhuǎn)換器的示例。 如您所見(jiàn),轉(zhuǎn)換器非常簡(jiǎn)單。 在將實(shí)體持久存儲(chǔ)到數(shù)據(jù)庫(kù)之前,hibernate會(huì)調(diào)用convertToDatabaseColumn方法。 它從實(shí)體獲取未加密的字符串,并使用帶有PKCS5Padding的AES算法進(jìn)行加密。 然后,使用base64編碼將加密的byte []轉(zhuǎn)換為字符串 ,該字符串將保留在數(shù)據(jù)庫(kù)中。
當(dāng)持久性提供程序從數(shù)據(jù)庫(kù)讀取實(shí)體時(shí),將調(diào)用convertToEntityAttribute方法。 它從數(shù)據(jù)庫(kù)中獲取加密的String ,使用base64解碼將其轉(zhuǎn)換為byte []并執(zhí)行解密。 解密后的字符串將分配給實(shí)體的屬性。
對(duì)于真實(shí)的應(yīng)用程序,您可能需要花費(fèi)更多的精力進(jìn)行加密或?qū)⑵湟浦羻为?dú)的類(lèi)。 但這足以說(shuō)明一般想法。
@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);}} }好的,我們有一個(gè)類(lèi)型轉(zhuǎn)換器,可以對(duì)字符串進(jìn)行加密和解密。 現(xiàn)在,我們需要告訴休眠模式使用該轉(zhuǎn)換器來(lái)保留CreditCard實(shí)體的ccNumber屬性。 如前一篇文章中所述 ,我們可以使用@Convert注釋。 但這將更改我們應(yīng)用程序的代碼。
另一個(gè)也是我們的要求,更好的選擇是在XML配置中分配轉(zhuǎn)換器。 這可以在orm.xml文件中完成。 以下代碼段將CryptoConverter分配給CreditCard實(shí)體的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>這就是我們?yōu)閱蝹€(gè)數(shù)據(jù)庫(kù)字段實(shí)現(xiàn)和配置基于類(lèi)型轉(zhuǎn)換器的加密所需要做的一切。
實(shí)體偵聽(tīng)器還是類(lèi)型轉(zhuǎn)換器?
這個(gè)問(wèn)題的答案并不像看起來(lái)那樣容易。 兩種解決方案都有其優(yōu)點(diǎn)和缺點(diǎn)。
Bear Giles描述的實(shí)體偵聽(tīng)器可以在加密過(guò)程中使用實(shí)體的多個(gè)屬性。 因此,您可以加入多個(gè)屬性,對(duì)其進(jìn)行加密,然后將加密的數(shù)據(jù)存儲(chǔ)在一個(gè)數(shù)據(jù)庫(kù)字段中。 或者,您可以對(duì)加密和解密的數(shù)據(jù)使用不同的屬性,以避免對(duì)解密的數(shù)據(jù)進(jìn)行序列化( 如Bear Giles所述 )。 但是使用實(shí)體偵聽(tīng)器也有缺點(diǎn)。 它的實(shí)現(xiàn)特定于實(shí)體,并且比類(lèi)型轉(zhuǎn)換器的實(shí)現(xiàn)復(fù)雜。 而且,如果需要加密其他屬性,則需要更改實(shí)現(xiàn)。
如您在上面的示例中所看到的,類(lèi)型轉(zhuǎn)換器的實(shí)現(xiàn)既簡(jiǎn)單又可重用。 CryptoConverter可以用于加密任何實(shí)體的任何String屬性。 并且通過(guò)使用基于XML的配置將轉(zhuǎn)換器注冊(cè)到實(shí)體屬性,它不需要更改應(yīng)用程序的源代碼。 如果遷移現(xiàn)有數(shù)據(jù),您甚至可以在以后的某個(gè)時(shí)間將其添加到應(yīng)用程序中。 該解決方案的缺點(diǎn)是,加密的實(shí)體屬性不能標(biāo)記為瞬態(tài)。 如果將實(shí)體寫(xiě)入磁盤(pán),則可能會(huì)導(dǎo)致漏洞。
您會(huì)看到,兩種方法都有其優(yōu)缺點(diǎn)。 您必須決定哪些優(yōu)點(diǎn)和缺點(diǎn)對(duì)您來(lái)說(shuō)更重要。
結(jié)論
在本文的開(kāi)頭,我們定義了3個(gè)要求:
- 提供不影響應(yīng)用程序的透明加密,
- 能夠在部署時(shí)添加加密,
- 由兩個(gè)不同的團(tuán)隊(duì)/人員開(kāi)發(fā)應(yīng)用程序和安全性/加密。
所描述的CryptoConverter實(shí)現(xiàn)實(shí)現(xiàn)了所有這些。 如果使用XML配置分配類(lèi)型轉(zhuǎn)換器,則可以在部署時(shí)添加加密,并且不會(huì)影響應(yīng)用程序。 應(yīng)用程序的開(kāi)發(fā)和加密是完全獨(dú)立的,可以由不同的團(tuán)隊(duì)來(lái)完成。 最重要的是,CryptoConverter可用于轉(zhuǎn)換任何實(shí)體的任何String屬性。 因此具有很高的可重用性。 但是,正如我們?cè)谏弦欢沃锌吹降哪菢?#xff0c;此解決方案也存在一些缺點(diǎn)。
您必須決定要使用哪種方法。 請(qǐng)給我評(píng)論您的選擇。
翻譯自: https://www.javacodegeeks.com/2014/06/how-to-use-a-jpa-type-converter-to-encrypt-your-data.html
總結(jié)
以上是生活随笔為你收集整理的如何使用JPA Type Converter加密数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 寅年是哪一年 什么年份
- 下一篇: 知了吃什么食物 知了吃的食物有什么