【问题标题】:matching user's password from record in db从数据库中的记录匹配用户的密码
【发布时间】:2011-07-06 08:52:15
【问题描述】:

在我使用 servlet 和休眠的网络应用程序中。我需要验证输入密码的客户。

如果他已经在数据库中,我需要检查他的密码是否与数据库中记录的密码匹配。对于新客户,我想获取密码并为他创建记录。 我尝试在场景中这样做。

现有客户输入电子邮件地址和密码

String email = req.getParameter("emailAddress");
String password = req.getParameter("password");
Customer cust = dao.findByEmailAddress(email);

现在,我如何检查此 cust 对象是否与密码相关联并且与用户输入的内容相匹配? Manning 的休眠书示例将密码作为字符串存储在 Customer 类中。这是一个好主意吗?这将如何存储在数据库中?

使用hibernate时,如何处理?我听说有人提到将密码存储为哈希。但我不太确定如何在我的应用中做到这一点。

谁能告诉我如何解决这个问题?

【问题讨论】:

    标签: java hibernate passwords hash


    【解决方案1】:

    存储纯文本密码绝不是一个好主意。事实上,它在Top 25 Most Dangerous Software Errors 中被列为#8 威胁。

    您需要在将密码写入数据库之前对其进行加密。搜索用户时使用加密密码

    String email = req.getParameter("emailAddress");
    String password = req.getParameter("password");
    String encryptedPassword = MD5Helper.hashPassword(password)
    Customer cust = dao.findByEmailAddressAndPassword(email, encryptedPassword);
    

    您可以使用类似这样的方法使用 MD5 算法加密密码。

    public class MD5Helper {
    
        private static final int MD5_PASSWORD_LENGTH = 16;
    
        public static String hashPassword(String password) {
            String hashword = null;
            try {
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                md5.update(password.getBytes());
                BigInteger hash = new BigInteger(1, md5.digest());
                hashword = hash.toString(MD5_PASSWORD_LENGTH);
            } catch (NoSuchAlgorithmException nsae) {
                // handle exception
            }
            return hashword;
        }
    }
    

    【讨论】:

    • 哈希(或消息摘要)不是加密。加密需要密钥。可以使用此密钥对加密数据进行解密。哈希不能被取消哈希。
    • 对密码进行哈希处理而不加盐会使它容易受到字典攻击。
    【解决方案2】:

    您必须决定如何存储密码。如果将它们作为字符串存储在 Hibernate 实体中,它们将以明文形式存储在数据库中的 varchar 中。因此,任何有权访问数据库的人都可以看到它们。在这种情况下,身份验证包括将发送的密码与数据库中的密码进行比较。

    还有两种可能

    第一个是在将它们存储到数据库之前使用密钥对其进行加密。但是这个密钥必须存储在某个地方,以便您的应用程序解密它们并将解密的密码与用户发送的密码进行比较。但它至少可以减少只有有权访问应用程序部署目录的人才能看到密码。在这种情况下,身份验证包括使用密钥解密存储在数据库中的密码,并将其与用户发送的密码进行比较。如果它们相等,则用户发送了正确的密码。

    最后一种可能性是使用单向哈希算法(例如 SHA-1),也称为消息摘要算法。这样,就不需要密钥,任何人都很难(阅读:几乎不可能)访问密码(如果密码被加盐)。此解决方案的缺点是,如果用户丢失了密码,您将无法发送给他。唯一的可能是将他重置为新值,将此新密码发送给用户并要求他选择一个新密码。在这种情况下,对用户进行身份验证包括对他发送的密码进行哈希处理,并与存储在数据库中的哈希值进行比较。

    阅读http://en.wikipedia.org/wiki/Salt_(cryptography) 了解更详细的说明。

    【讨论】:

    • 感谢您的回复..,使用哈希似乎是一种选择..要创建客户,我想我必须对用户的密码输入进行哈希处理,调用 customer.setPassword(hashedpass) 和然后在 customerdao 上调用 saveUpdate() 以便将哈希写入 Customer 表中。为了验证,我必须对用户输入进行哈希处理,从 db 获取 hashedpass,然后匹配它们。这样正确吗?
    • 是的,就是这样。如果您真的想要安全存储,请在散列密码之前对密码进行加盐。
    【解决方案3】:

    通常密码以加密方式存储在数据库中,您必须对输入的密码进行加密以检查其是否匹配。

    String passwordEncrypted = encrypt(password);
    

    encrypt 是您加密密码的函数(例如,您可以尝试使用 MD5 或 SHA-1)。

    在您检索到您的对象cust 后,您可以检查是否

    if (cust.getPassword().equals(passwordEncrypted)) {
        // login successfull code
    } else {
        // login failed code
    }
    

    【讨论】:

    • 哈希(或消息摘要)不是加密。加密需要密钥。可以使用此密钥对加密数据进行解密。哈希不能被取消哈希。
    • 对密码进行哈希处理而不加盐会使它容易受到字典攻击。
    猜你喜欢
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 1970-01-01
    • 2013-08-27
    • 2018-05-12
    • 1970-01-01
    • 2014-08-18
    相关资源
    最近更新 更多