2017-10-30 15 views
0

Knockでユーザーレコードを更新するときにユーザーの現在のパスワードを要求しようとしています。私はpassword_digestを作成するのと同じプロセスで投稿されたパスワードを実行できると思っていましたが、作成されたハッシュを比較するときはいつでも違います。ユーザー入力をハッシュするときに何か不足していますか?Knockで更新時にパスワードを要求する

これは私の更新方法である

def update 

    @user = current_user 

    # hash current password 
    @current_password = params[:current_password] 
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost 
    @hashed_password = BCrypt::Password.create(@current_password, cost: cost) 


    # return if no current password is given 
    if @current_password != nil 

    # compare and continue if they match 
    if @hashed_password === current_user.password_digest 

     # try to update record 
     if @user.update_attributes(user_params) 
     render json: @user 
     else 
     render json: @user.errors.full_messages 
     end 

    # otherwise return password error 
    else 
     render json: { message: "Your current password is incorrect" } 
    end 

    else 
    render json: { message: "You must provide your current password" } 
    end 
end 

編集:ユーザーは私が正しく理解していれば、ActiveModelでthis callをトリガするユーザーモデル、上has_secure_passwordで保存され。私はbyebugを使用して実行を停止し、割り当て後の変数を比較しましたが、実際は異なっています。

編集2:誰もが将来的にこの横切ると同様の戦略を使用したい場合、あなたはそれはあなたが評価するcurrent_passwordのparamに合格できるようになるように、あなたのUserモデルにattr_accessor :current_passwordを追加する必要があります。

+0

元のパスワードはどこでハッシュされていますか?論理は同じですか?また、なぜ比較のために '=='の代わりに '==='を使用していますか?ハッシュされている元のパスワードに関連するコードを追加してください。 'pry-rails'を使って実行を停止し、' @ hashed_pa​​ssword'と 'current_user.password_digest'で値をチェックしようとしましたか? – Genzume

+0

保存する前にユーザーパスワードをハッシュする元のメソッドへのリンクを追加しました。私はそれらをチェックした、彼らは異なる値です。ケースの平等はここでは適切ではないのですか? – oneWorkingHeadphone

+1

'==='はオブジェクト・エクイティです。たとえば、 '' foo "===" foo "'は、異なるオブジェクトであるため文字列がフリーズしない限り、falseです。 '" foo "==" foo "'は値を比較します。 – max

答えて

1

Bcryptを繰り返し実行すると、同じ入力でも同じ出力が生成されません。むしろ、ブルートフォースアタックをはるかに高価にする任意の組み合わせに対して、可能なアウトプットが多数存在する。入力が正しいパスワードを使用している場合は、ActiveModel :: SecurePasswordを使用しているので、あなたが@user.authenticate(password)とパスワードを確認することができますBCrypt::Password#is_password?

BCrypt::Password.new(password_digest).is_password?(unencrypted_password) 

確認するには

def update 
    @user = current_user 
    unless @user.authenticate(params[:current_password]) 
    @user.errors.add(:current_password, "is incorrect") 
    end 
    if @user.update(user_params) 
    render json: @user 
    else 
    render json: @user.errors.full_messages, status: :unproccessable_entity 
    end 
end 
+0

どちらも完璧に機能しました!ありがとう、インクルードも物事をきれいにするのに役立ちます。 – oneWorkingHeadphone

+0

私は、ActiveModel :: SecurePasswordを2度目の読み込みでどこで使用するのかを見てきました。 – max

+0

ええ、実際には、この文でif文をifで置き換えようとすると、今度はすべてのパスワードを受け入れます。私はあなたの答えに基づいている最後の作業コードです。https://pastebin.com/kU83EWLe – oneWorkingHeadphone

0

私はあなたがBcryptのパスワードを比較できるとは思わない。 Bcryptはハッシュアルゴリズムであり、hash_secretによって使用されるすべての作成時にキーを生成します。これにより、毎回ハッシュが異なります。例:

irb(main):010:0> instance = BCrypt::Password.create('secret') 
=> "$2a$10$FT8YdmzJIkOceKhZ/DwXluYNGm.lZj0Jfrx2nQqzxxM1IX767gNmG" 
irb(main):011:0> instance_two = BCrypt::Password.create('secret') 
=> "$2a$10$ECA8HoTSuxAvAbFbbg6jQ.g4uIcZqYbNCckfGIzLePfSTx2OM0zJS" 
irb(main):012:0> instance == instance_two 
=> false 
irb(main):013:0> 
関連する問題