jpa 返回数据转换_如何使用JPA类型转换器加密数据
jpa 返回數據轉換
幾天前,我讀了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包含Hibernate4.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);}} }好的,我們有一個可以對String進行加密和解密的類型轉換器。 現在我們需要告訴hibernate使用此轉換器來保留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 返回數據轉換
總結
以上是生活随笔為你收集整理的jpa 返回数据转换_如何使用JPA类型转换器加密数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Boot中的@Spring
- 下一篇: 还不会做图表可视化,那你千万不能错过这个