2

我需要修改一个安全的登录代码:

@Override
public User login(String username, String password, Boolean rememberMe) {   
    log.info("Logging in username="+username);
    UsernamePasswordToken token;
    String hashed = BCrypt.hashpw(password, BCrypt.gensalt());
    log.info("Hashed password=" + hashed);
    token = new UsernamePasswordToken(username, hashed);
    // ”Remember Me” built-in, just do this:
    token.setRememberMe(rememberMe);
    try {
        // With most of Shiro, you'll always want to make sure you're working with the currently executing user,
        // referred to as the subject
        Subject currentUser = SecurityUtils.getSubject();

        // Authenticate
        //currentUser.login(token);     
        User user = userDAO.fetchUserByName(username, hashed);
        return user;
    } catch (org.apache.shiro.authc.AuthenticationException e) {
        throw new AuthenticationException("Failure in authentication");
    } catch (IllegalStateException e){
        throw new AuthenticationException("Application is in a illegal state");
    } catch (Exception e){
        throw new AuthenticationException("Some other error during login was caught.");
    }
}

在 DAO 级别:

  • 使用用户名和哈希密码获取用户对象

但是,现在,存储在数据库中的密码是普通密码,我将用散列密码替换它。这里的问题是:

  • BCrypt.hashpw() 方法生成不同的哈希,正如我在记录此代码时看到的那样。

所以问题是如何在每次更改时存储散列密码。

我的想法是

  • 用户在 UI 中输入明文密码,在这个登录方法中,密码会被哈希,然后通过 fetchUserByName(username, hashed) 方法获取用户;但这似乎不是这种特殊的 Shiro 和 BCrypt 组合的解决方案。

处理这个问题的正确方法是什么?

4

2 回答 2

3

您应该知道,由此产生的“散列密码”hashpw()不仅仅是散列。它还包含您作为纯文本传入的随机生成的盐。

BCrypt.checkpw(password, storedHash)是检查存储散列的正确方法。该方法将从“哈希密码”中检索盐,对明文密码进行哈希处理,并将结果与storedHash​​ .

您可以在此处找到有关如何使用该库的更详细说明。

在你的情况下,我会写这样的方法:

public User login(String username, String password) {  
    User user = userDAO.fetchUserByName(username);
    if (!BCrypt.checkpw(password, user.getHash()) 
        throw new AuthenticationException("Failure in authentication");
    return user;
}
于 2013-07-26T00:44:03.723 回答
3

BCrypt.hashpw 方法不会为多次迭代返回相同的密码哈希。

您需要使用 BCrypt 类的 checkpw 方法比较不同的哈希密码(一个是新创建的,一个在数据库中)。

BCrypt.gensalt() 在您的方法中正确使用。只需根据用户名检索用户信息,并使用 checkpw 方法比较散列密码。

我希望它有所帮助。

于 2013-07-25T20:03:24.280 回答