【问题标题】:How can I design an JPA entity setter that depends on business code?如何设计依赖于业务代码的 JPA 实体设置器?
【发布时间】:2016-05-05 23:23:44
【问题描述】:

我有以下实体:

@Entity
public class User {

    @Id
    private Integer id;

    private String username;
    private String password;

}

要设置密码,必须提供明文密码,但实际存储的密码是明文密码的哈希值。问题是实际的哈希计算取决于业务。更具体地说,我有以下接口和 Session Bean:

public interface PasswordHash {
    String hash(String password);
}

@Stateless
public class UserManager {

    @Inject
    private PasswordHash phash;

    public void changeUserPassword(User user, String newPassword) {
        String passwordHash = phash.hash(newPassword);
        /*Set password of 'user'*/
    }
}

有没有办法为用户实体的“密码”字段设计一个设置器,以便 UserManager 可以更改其值,但没有其他人可以做到这一点?如果不可能,是否有另一种方法可以安全地设置密码,而不会将 PasswordHash 接口暴露给客户端?请注意,CDI 不适用于 Entity 类,因此我无法将 PasswordHash 的实例直接注入其中。

【问题讨论】:

  • @BalusC 但我需要在某处定义password,并且必须与username 在同一张桌子上,因为我正在使用容器管理的安全性和表单登录。除此之外,还有其他类似情况发生的情况,如果我能在不更改实际持久数据定义的情况下解决这个问题会更好。
  • 我真的不明白问题出在哪里。你不能使用@PrePersist@PreUpdate 函数并且在实体上可能有@Transient PasswordHash hasher 属性吗?
  • @coladict 问题是不能从User 实体公开此行为,因为这是一个业务问题。实际的PasswordHash 实现仅可通过CDI 提供给UserManager 类,因为该类负责业务逻辑。如果我让UserManager 成为实体侦听器,我可以使用@PrePersist@PreUpdate,但我必须检查密码是否真的被更改了,我试图避免这种情况。

标签: jpa jakarta-ee ejb cdi


【解决方案1】:

处理此问题的一种方法是不要直接从您的服务层公开用户实体,仅在内部使用它以实现持久性。你通常最终做的基本上是复制一些实体,然后来回复制东西。这些“复制”的类有时称为数据传输对象。有像Dozer 这样的工具可以让这更容易,虽然可以说不是更漂亮。

第二种方法是对抗 Enterprise Java,并避免这些Anemic Objects。不过,迟早您可能必须进行编程查找,因为正如您所说,实体不支持 CDI。这也不是很漂亮,但至少你会得到一些更面向对象的东西。

【讨论】:

  • 我倾向于在User 实体上使用setPassword(UserManager manager, String plainTextPassword) 方法,该方法只调用UserManager.changeUserPassword(),这样客户端将无法在不涉及UserManager 的情况下直接更改密码。这不完全是二传手,但可以做我想做的事。你怎么看?
  • 好吧,如果你有 UserManager,我只会在 User 对象本身中提供 set/getPasswordHash。这意味着,如果另一个对象想要更改密码,它必须在设置之前获取 UserMaanger 并生成散列。此外,您可以创建一个 Hash 类以避免将非散列字符串意外设置到用户中。
  • 我喜欢这个主意。我可以使Hash 类成为UserManager 的内部而没有公共构造函数,并且有一个方法,比如UserManager.createHash(String password),这是获取Hash 实例的唯一方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-03
  • 1970-01-01
  • 2011-02-02
  • 2011-12-12
相关资源
最近更新 更多