2 votes

Stockage du mot de passe haché

J'ai besoin de réorganiser un code de connexion sécurisé :

@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.");
    }
}

Au niveau de la DAO :

  • L'objet utilisateur est récupéré avec le nom d'utilisateur et le mot de passe haché.

Cependant, pour l'instant, le mot de passe stocké dans la base de données est simple, je vais simplement le remplacer par un mot de passe haché. Le problème ici est le suivant :

  • La méthode BCrypt.hashpw() génère un hash différent comme je peux le voir lorsque j'ai enregistré ce code.

La question serait donc de savoir comment stocker un mot de passe haché lorsqu'il change à chaque fois.

L'idée à laquelle je pensais est que

  • L'utilisateur saisit le mot de passe brut dans l'interface utilisateur, et dans cette méthode de connexion, le mot de passe sera haché puis l'utilisateur sera récupéré par la méthode fetchUserByName(username, hashed) ; mais cela ne semble pas être la solution pour ce mélange particulier de Shiro et BCrypt.

Quelle est la bonne façon d'aborder cette question ?

3voto

PankajSays Points 685

La méthode BCrypt.hashpw ne retournera pas le même hachage de mot de passe pour plusieurs itérations.

Vous devrez comparer les différents mots de passe de hachage (un créé récemment et un dans la base de données) en utilisant la méthode checkpw de la classe BCrypt.

BCrypt.gensalt() est correctement utilisé dans votre méthode. Il suffit de récupérer les informations de l'utilisateur sur la base du nom d'utilisateur uniquement et de comparer le mot de passe haché en utilisant la méthode checkpw.

J'espère que cela vous aidera.

3voto

Vous devez être conscient que le "mot de passe haché" qui résulte de hashpw() n'est pas seulement un hash. Il contient également le sel généré aléatoirement que vous avez transmis en clair.

BCrypt.checkpw(password, storedHash) est la manière correcte de vérifier par rapport à un hachage stocké. La méthode va récupérer le sel du "mot de passe haché", hacher le mot de passe en clair, et comparer le résultat à la portion de hachage réelle de storedHash .

Vous pouvez trouver une description plus détaillée de la façon d'utiliser la bibliothèque aquí .

Dans votre cas, j'écrirais la méthode comme ceci :

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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X