繁体   English   中英

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

[英]Proper way to validate password in Java from SQL database?

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

我是不是该:

  1. 根据用户名查询密码并在Java应用程序中对其进行验证? (从用户名为'foo'的用户中选择密码)

  2. 根据用户名和密码输入查询行? (在用户名='foo'和密码='bar'的用户中选择true)

  3. 完全是其他东西...

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

编辑:

好的,也许我在与PASSWORD相同的帖子中使用了单词TEXT犯了一个错误,但是我指的是数据类型,而不是说我将密码保存为纯文本格式。 实际上,我明确地问过“将密码哈希输入Java的正确方法是什么”。 请坚持我问您想提供帮助的问题。

散列密码。 比您可以比较的哈希值。

从用户那里选择用户名,其中用户名=用户名和密码_哈希=密码_哈希;

如何在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));

这两种方法都不好,因为密码可能是通过网络在应用程序外部以纯文本格式传输的。 但是第二种方法稍好一些,因为某些传输密码有时会出错。

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

选项3:完全不同。

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

步骤2:从密码哈希中提取

步骤3:使用Salt从用户收到的纯文本中计算哈希

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

认真 :阅读盐腌的密码哈希。 这是存储密码的唯一正确方法。 最好的是,它已经存在。 除非您是密码学天才(否则您应该更了解),否则甚至不要尝试重新发明这个轮子。

不要忘记哈希。 当两个用户恰好选择相同的密码时,它可以防止两个用户具有相同的哈希。 另外,它在很大程度上避免了字典攻击,例如彩虹表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM