J'ai commencé à travailler sur un projet qui avait déjà beaucoup de code en place. C'est une application Ruby on Rail qui utilise Devise pour l'authentification des utilisateurs. L'une des exigences de l'application est que lorsqu'un utilisateur change son mot de passe, il n'est pas autorisé à utiliser le même mot de passe que les trois derniers mots de passe précédemment utilisés. Pour accomplir ceci, il y a une table qui contient un historique des mots de passe pour un utilisateur donné. Ces mots de passe sont des copies des mots de passe cryptés qui existaient avant tout changement de mot de passe sur l'utilisateur.Cryptage des mots de passe pour correspondre aux mots de passe cryptés stockés.
Voici où le problème entre en jeu. Nous avons un formulaire de changement de mot de passe qui recueille le nouveau mot de passe pour un utilisateur donné. Je dois être en mesure de prendre le nouveau mot de passe et de le crypter afin que je puisse faire correspondre la valeur cryptée du nouveau mot de passe avec les valeurs cryptées des anciens mots de passe dans l'histoire.
trucs techniques
Rails Version 3.0.9
version 1.3.4
Devise Utilisation Bcrypt standard avec. Devise bcrypt_ruby version 2.1.4
Pour cela, nous sommes en train de surcharger la méthode reset_password supportée par Devise. Cela nous permet d'introduire notre propre méthode, has_repeated_password dans le contrôleur de l'utilisateur.
La version de has_repeated_password j'ai commencé avec est ci-dessous:
def has_repeated_password?
return false if self.new_record? || self.version == 1
histories = self.versions.find(:all, :order => 'version DESC', :limit => 3)
histories.detect do |history|
history.encrypted_password == self.class.encryptor_class.digest(self.password, self.class.stretches, history.password_salt, self.class.pepper)
end
end
Le problème ici est que la classe chiffreur est jamais définie, ce qui provoque une erreur à chaque fois que cette routine se exécute. Même s'il existe de nombreux exemples qui prétendent que cela fonctionne, je ne peux pas le faire fonctionner lorsque Devise utilise le cryptage par défaut.
Une deuxième tentative de c'est le code suivant:
def has_repeated_password?<br>
return false if self.new_record? || self.version == 1
histories = self.versions.find(:all, :order => 'version DESC', :limit => 3)
histories.detect do |history|
pwd = self.password_digest(self.password)
history.encrypted_password == pwd
end
end
Dans ce cas, je ne reçois jamais un mot de passe qui correspond à l'un des mots de passe stockés, même si je l'ai vérifié que le mot de passe dans la base de données ce que j'attends.
J'ai essayé de creuser le code Devise pour voir ce que je peux y trouver. Je sais que l'autentication doit le faire d'une manière ou d'une autre quand elle fait correspondre les mots de passe collectés des utilisateurs avec le mot de passe stocké.
Toute aide serait appréciée.
Il est plus correct d'utiliser 'p = BCrypt :: Password.new (history.encrypted_password)' et ensuite 'p == password'. La classe 'BCrypt :: Password' a l'opérateur' == 'défini. –