从SQL数据库验证Java密码的正确方法?

时间:2012-02-07 20:46:04

标签: java passwords

我正在尝试确定在Java中实现密码验证的最佳方法。密码作为文本存储在SQL数据库中。

我应该:

  1. 根据用户名查询密码并在Java应用程序中验证? (SELECT users FROM users WHERE username ='foo')

  2. 根据用户名+密码输入查询行? (SELECT true FROM users WHERE username ='foo'和password ='bar')

  3. 其他完全......
  4. 如果答案是#1,那么将密码哈希变为Java的正确方法是什么?我知道密码应该存储为char []而不是String,以避免在内存中留下副本,但是可以使用ResultSet.getString(“password”)从结果集中检索它吗?不会创建一个String常量并且存在安全风险(即使是散列)?我看到的另一个选项是将密码存储/转换为SQL中的数组,然后使用ResultSet.getArray()来检索它,但除非绝对必要,否则这似乎有点过分。

    修改

    好吧,也许我在与PASSWORD相同的帖子中使用TEXT这个词时犯了一个错误,但我指的是数据类型,而不是说我用纯文本保存密码。事实上,我清楚地问过“将密码哈希转换为Java的正确方法是什么”。如果你想提供帮助,请坚持我问的问题。

3 个答案:

答案 0 :(得分:0)

哈希密码。比你可以比较哈希。

SELECT username FROM user WHERE username = username and password_hash = password_hash;

How can I hash a password in Java?

byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 2048, 160);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = f.generateSecret(spec).getEncoded();
System.out.println("salt: " + new BigInteger(1, salt).toString(16));
System.out.println("hash: " + new BigInteger(1, hash).toString(16));

答案 1 :(得分:0)

您的方法都很糟糕,因为密码在应用程序之外以纯文本传输,可能是通过网络传输。但第二种方法略胜一筹,因为有些传输密码有时会出错。

使用某种散列。哈希密码然后将其存储到数据库中。哈希也输入密码并比较哈希值。散列是不可逆转的数据转换。使用MessageDigest类http://docs.oracle.com/javase/6/docs/api/java/security/MessageDigest.html在Java中创建哈希。使用你的数据库知道的一个。

答案 2 :(得分:0)

选项3:完全不同。

第1步: SELECT passwordHASH from users WHERE username=?(注意占位符以避免SQL注入攻击 - 检查您的API如何使用占位符)

第2步:从密码哈希中提取 salt

步骤3:使用salt根据从用户

收到的纯文本计算哈希值

步骤4:将现有的passwordHash与新计算的passwordHash进行比较。

认真:阅读盐渍密码哈希值。这是唯一正确的密码存储方式。最好的是,它已经存在。不要试图重新发明这个轮子,除非你是一个加密天才(然后你应该知道更好)。

不要把哈希留下来。当两个用户碰巧选择相同的密码时,它会阻止两个用户使用相同的哈希值。此外,它在很大程度上避免了字典攻击,例如彩虹表。