1

我对以下情况有疑问:

在我的 Spring,Hibernate 应用程序中,我得到了一个 User Entity 和一个 UserCategory Entity。用户实体的表有一个用户名作为标识符。此标识符字段无法加密,因为此表也被旧程序使用,无法执行此操作。

要从 UserCategory 对 User 进行 ManyToOne 引用,我需要 UserCategory 表中的一个字段,其中包含用户的唯一用户名。我想要做的是使用 Jasypt 加密 UserCategory 表中的用户名。当然,这项工作:

    @Type(type="encryptedString") 
    @ManyToOne 
    @JoinColumn(name = "username", insertable=false, updatable=false)   
    @ForeignKey(name = "none") 
    public User getUser(){ 
            return this.user; 
    } 
    public void setUser(User user ){ 
            this.user = user; 
    } 

但是在将加密的用户名放入 UserCategory 表后,我无法使用此记录,因为 Hibernate 无法在加密字段上引用用户:您将收到以下错误:

"No row with the given identifier exists: com.foo.bar.models.User#M9LgndiyCsVGqfVRVblb3A=="

这是一个逻辑错误,但你知道一个好的解决方案吗?认为代码需要先解密然后尝试进行引用。但我坚持如何做到这一点。

4

1 回答 1

1

我认为您误解了如何使用自定义用户类型,并且正如我在之前的回答中所评论的那样,您不应该在这里在关联级别声明自定义类型,您应该在属性级别使用它,即在username属性上的User实体。

这实际上在文档中进行了解释(从 Google Cache 粘贴,因为 Jasypt 站点目前似乎已关闭):

将 Jasypt 与 Hibernate 3 集成

Jasypt 提供了一个集成包 ( org.jasypt.hibernate.type),它提供了几个 HibernateUserType 实现,以允许将映射的 Hibernate 实体中的一个或多个属性声明为加密类型。允许加密存储的类型包括字符串、二进制文件(字节数组)、数字类型、布尔值和日期。

这些属性的持久性将以加密的方式完成,但对应用程序来说是完全透明的方式。

这对于加密个人数据、私人消息等很有用,因此可以避免任何对“关键”表具有读取权限的人都可以读取其所有内容。

对于 Hibernate 的加密,jasypt 使用其基于密码的加密功能,任何实现 PBEStringEncryptor、PBEByteEncryptor、PBEBigIntegerEncryptor 或 PBEBigDecimalEncryptor 的加密器对象都可用于加密数据,甚至是用户创建的加密器。

但是加密对您的 Hibernate 使用设置了限制:安全标准规定,对相同数据的两种不同加密操作不应返回相同的值(由于使用了随机盐)。因此,在持久化时设置为加密的任何字段都不能成为它们所属实体的搜索查询中的 WHERE 子句的一部分

因此,总而言之,1)@Type注释应该应用于username2)您将无法使用usernameas 主键(因为它不能成为上面最后一段中提到的连接的一部分)。

这意味着您将需要这样的东西(假设您声明了适当的@TypeDef):

@Entity
public class User {

    @Id @GeneratedValue
    private Long id;

    @Type(type="encryptedString") 
    private String username;

    ...
}

并相应地修改ManyToOne关联。

于 2010-07-20T17:15:36.510 回答