MySQL中的列应该自动散列插入的值(使用Hibernate和Java)

MySQL中的列应该自动散列插入的值(使用Hibernate和Java),java,mysql,hibernate,Java,Mysql,Hibernate,我有一些Java对象,使用hibernate,例如: @Entity class User { @Id private int id; @Column private String name; @Column private String pw; public User() {} public String getName() { return name; } public void setName(String

我有一些Java对象,使用hibernate,例如:

@Entity
class User {

    @Id
    private int id;

    @Column
    private String name;

    @Column
    private String pw;

    public User() {}

    public String getName() { return name; }
    public void setName(String name) { this.name = name;}
    public String getPw() { return pw; }
    public void setPw(String pw) { this.pw = pw; }
}
当我实例化一个新的用户对象时,我会像这样手动散列一个字符串

User user1 = new User();
user1.setPw(hashPw("MyPassword"));
它工作得很好,但我想要的是像这样使用setter

user1.setPw("MyPassword")
我希望数据库使用SHA-512算法(或者您推荐的任何也可以在Java中使用的算法)自动对字符串进行散列

我想告诉数据库,当它被创建时,这个列必须被散列

我完全用hibernate构建了数据库,这是我的新手。 ATM I使用utf8字符集将哈希保存在char(128)列中,不可为空

编辑:

最好是在java代码中使用hibernate/jpa中的注释

编辑:

我的应用程序的第一步是用数据填充数据库。在那之后,我将只使用对象,可能不再更改它们的任何值,所以当我第一次插入真实数据(测试数据atm)时,我需要哈希步骤。我已经尝试过这样的公式注释:

// ...
@Formula("SHA2(pw,512)")
private String pw;
// ...
但在那之后,这一列就不完整了

编辑:

我将尝试展示我如何想象一个可能的解决方案:

  • 实例化一个新的用户对象user1
  • 像user1.setUnhashedPassword(“MyPassword”)一样设置未加密的密码
  • 打开一个新的会话
  • 开始交易
  • 保存对象user1
  • 结束交易
  • 闭门会议
  • 从数据库获取数据
  • 打印列“哈希密码”

  • 所有这些,在我的java代码中没有任何哈希逻辑。

    鉴于您在同一个类中处理哈希密码和未哈希密码,您必须明确区分哈希密码和未哈希密码

    定义为
    @column private String pw的列
    是个坏主意,因为它回避了以下问题:这是什么?这是散列密码还是未散列密码?
    getPw()
    将返回什么?如果调用
    setPw(“mypassword”)

    因此,不要只使用名为“password”的标识符,始终使用诸如“hashedPassword”和“unhashedPassword”之类的标识符

    因此,我建议:

    @Column 
    private String hashedPassword; 
    
    public String getHashedPassword() 
    {
        return hashedPassword;
    }
    
    public void setHashedPassword( String hashedPassword ) 
    {
        this.hashedPassword = hashedPassword;
    } 
    
    public String setUnhashedPassword( String unhashedPassword ) //no getter!
    {
        String temp = hashPw( unhashedPassword );
        setHashedPassword( temp );
    }
    

    在保存之前对拦截器进行哈希怎么样?您应该查找“@PrePersist”和“@PreUpdate”注释。使用这些,您可以确保每次将实体持久化到数据库中时,所需的列都会被散列。好的,我查看了
    PrePersist
    PreUpdate
    注释,但在那里它用于临时属性,但我将尝试它。您应该检查
    @Formula
    的定义,因为您完全误解了它的用例。顺便说一句,密码有一些特殊的哈希算法,比如。
    @PrePersist
    应该可以,但是
    @PreUpdate
    可能会导致问题。例如,当用户更新其姓名/电子邮件地址时,您不希望重新显示其密码。另一个选项是添加一个
    @Transient
    方法,如
    setPwPlaintext(stringplaintext)
    ,该方法进行哈希运算,然后相应地设置persistent属性。我同意,
    拦截器
    的杀伤力太大了。我上面的代码只是一个简单的例子,因为这不是我的问题(很抱歉,混乱,这里的第一个问题)。我使用的代码名称很清楚。问题是,在使用hibernate插入值或保存对象时,是否可以在数据库/hibernate站点执行此哈希操作。我将编辑我的文章,并写一个我如何想象的例子。我想我已经理解了。但是我的建议是“永远不要用魔法去做一些没有魔法也能轻易完成的事情”。散列是一个简单的操作。此外,在“hibernate端”执行此操作与将其构建到
    实体
    类中的setter中基本相同。要在数据库端执行此操作,您需要在数据库中使用本机查询或(更可能)自定义触发器。但是,您的解决方案将依赖于特定的数据库提供程序。这就是您想要的,还是您更愿意拥有可移植的代码,可以与hibernate可以对话的任何数据库提供程序一起使用?大多数时候,可移植代码比db magic更有价值。啊,好吧,现在我明白你的观点了,谢谢。好的,是的,通常我更喜欢可移植代码,但在这个特定的项目中,我认为我们只使用我将构建一次的mysql数据库。但是当我考虑它的时候,我想当我在代码中散列密码时,它会更安全,因为散列将被发送到DB,而不是发送到DB后散列的纯文本,可能稍后它会通过internet。但是,仅就我自己的知识而言,我仍然想知道,在这种情况下,我如何使用触发器来解决我的“问题”。