2013-03-26 63 views
4

我試圖實現一種方法,允許密碼從另一個服務之外的設計改變。Rails>設計密碼加密

# Profile password change 
def change_password(oldpass, newpass) 
    pepper = nil 
    cost = 10 

    # Encrypt plain text passwords 
    encrypt_old  = ::BCrypt::Password.create("#{oldpass}#{pepper}", :cost => cost).to_s 

    # Validate old 
    if self.encrypted_password == encrypt_old 
     encrypt_new  = ::BCrypt::Password.create("#{newpass}#{pepper}", :cost => cost).to_s 
     self.encrypted_password = encrypt_new 
     self.save 
    else 
     Logger.new("Wrong old password!") 
    end 
end 

看來我得到了密碼加密錯誤oldpass包含舊密碼的明文,我需要它哈希看它是否匹配,那麼當前的密碼允許存儲新的密碼。然而,我所得到的是錯誤的密碼。

返工:

def change_password(oldpass, newpass) 
    if valid_password?(oldpass) 
     password = newpass 
     save 
     return true 
    else 
     return false 
    end 
end 
+0

如果你使用的設計,那麼你就需要自己處理加密。設計默認使用加密:https://github.com/plataformatec/devise/blob/master/lib/generators/templates/devise.rb#L174 – joshhepworth 2013-03-26 21:04:10

回答

12

你並不需要自己加密的密碼,如果你是在應用程序或Rails的控制檯。

只需按照以下方式更新用戶,Devise將自行處理。

user.password = new_password 
user.save 

然後設計將加密密碼並存儲它。你只需要確保user.password_confirmationnil。如果password_confirmation是別的,它將與password匹配。

編輯

您可以檢查與現有的密碼:user.valid_password?(old_password)

+1

好吧,這是非常整潔,但我想先加密它的原因是:我舊密碼有3個字段1,新密碼有2個。 我需要看看他們輸入的舊密碼是否與存儲在模型中的舊密碼相匹配,如果確實存在,則存儲新密碼,否則會拋出錯誤的Flash消息。 – 2013-03-26 21:44:17

+0

好的,我更新了我的答案,檢查現有密碼是否正確。 – 2013-03-26 22:09:22

+0

看看我原來的帖子,我添加了更新的方法。即使tho方法返回true也不會真正改變密碼。 – 2013-03-26 22:27:21

4

隨着設計,您無需使用bcrypt自己來處理。默認情況下,它處理這個和更改密碼方法。您可以查看源文件here或只需在您的Rails應用程序中查找config/intitalizers/devise.rb

另外,如果您使用設計提供的#update_with_password方法,那麼你可以通過它的哈希是這樣的:

{ :current_password => 'pass', :password => 'pass_new', :password_confirmation => 'pass_new' } 

也可以忽略:password_confirmation,如果你不希望用戶必須提供一個確認。

編輯:我用錯了字段;它應該是'current_password'而不是'old_password'。

這裏的源問題的方法設計:

# Update record attributes when :current_password matches, otherwise returns 
    # error on :current_password. It also automatically rejects :password and 
    # :password_confirmation if they are blank. 
    def update_with_password(params, *options) 
    current_password = params.delete(:current_password) 

    if params[:password].blank? 
     params.delete(:password) 
     params.delete(:password_confirmation) if params[:password_confirmation].blank? 
    end 

    result = if valid_password?(current_password) 
     update_attributes(params, *options) 
    else 
     self.assign_attributes(params, *options) 
     self.valid? 
     self.errors.add(:current_password, current_password.blank? ? :blank : :invalid) 
     false 
    end 

    clean_up_passwords 
    result 
    end 

View on GitHub

+0

這給出了不能批量分配受保護的屬性:old_password by update_with_password – 2013-03-26 21:54:12

+0

因爲字段不可訪問而導致批量asign錯誤 - 模型需要具有'attr_accessible:old_password'。然而,我真的不知道,'old_password'是一個寫入數據庫的實際字段嗎? – ellmo 2013-03-27 10:21:14

+0

質量分配錯誤不應該發生,這是因爲它應該是'current_password'。這將告訴Devise驗證舊密碼,然後在一行代碼中進行更改。 – joshhepworth 2013-03-27 14:40:59