我在数据库(PostgreSQL)中有两个表,两个表都有一个作为主键的
id
字段,一个公共 example_id
和其他字段。
A { id, example_id, first_name, last_name } <- Here example_id is always encrypted
B { id, example_id, qty, beds } <- Here example_id is always in plain sight
当我从 A 插入和读取数据时,我使用
@ColumnTransformer
注释来使用 pgcrypto
内置函数对 example_id
字段进行编码和解码。
@ColumnTransformer(
forColumn = "example_id",
read = "pgp_sym_decrypt(example_id, 'my_key')",
write = "pgp_sym_encrypt(?, 'my_key')"
)
private String exampleId;
现在的问题是:如何在
example_id
字段上执行两个表之间的 JOIN?是否有 JPA 注释可以在执行匹配之前动态加密或解密列?可以在DB级别完成吗?或者我是否需要创建自定义 JPA 查询或将逻辑移至应用程序级别?
提前致谢
最终我通过简单的OneToOne关系解决了这个问题,底层框架自动执行加密值的读写。 它不会加密明文并比较密码,而是自动读取并解密第 i 条记录中的加密密码并进行比较。
但是,为了使其工作,我必须使用底层数据库的 current_setting 函数来纠正加密密钥的管理,因为不可能将环境密钥动态且轻松地注入到 JPA 注释中。此外,我必须指定安装
pgcrypto
函数的架构。
@ColumnTransformer(
forColumn = "example_id",
read = "public.pgp_sym_decrypt(example_id, current_setting('encryption.key'))",
write = "public.pgp_sym_encrypt(?, current_setting('encryption.key'))"
)
private String exampleId;
为此,我必须访问 postgresql.conf 文件并添加 encryption.key 属性,以便 current_setting 函数在数据库级别找到密钥。
encryption.key = 'my_key'
但是,请小心,因为密钥以明文形式存储在数据库中。最好通过函数或存储过程从外部系统检索它。