2011-12-11 17 views
25

新しいGrailsプロジェクトに登録機能を追加しました。それをテストするために、私は電子メールとパスワードを与えて登録しました。私はデータベースに保存する前に、パスワードをハッシュするためにbcryptアルゴリズムを使用しています。Bcryptは同じ入力に対して異なるハッシュを生成しますか?

ただし、登録時に入力した電子メールとパスワードでログインしようとすると、ログインに失敗します。私はアプリケーションをデバッグし、データベースから既にハッシュされたものと比較しようとすると、同じパスワードに対して生成されたハッシュが異なることを知り、ログインが失敗しています(Registration.findByEmailAndPassword(params.email、hashPassd) LoginController.groovyはヌルを返します。ここで

は、自分のドメインクラスRegistration.groovyです:

class Registration { 

    transient springSecurityService 

    String fullName 
    String password 
    String email 

    static constraints = { 
     fullName(blank:false) 
     password(blank:false, password:true) 
     email(blank:false, email:true, unique:true) 
    } 

    def beforeInsert = { 
     encodePassword() 
    } 

    protected void encodePassword() { 
     password = springSecurityService.encodePassword(password) 
    } 
} 

ここに私のLoginController.groovyです:

class LoginController { 

    /** 
    * Dependency injection for the springSecurityService. 
    */ 
    def springSecurityService 

    def index = { 
     if (springSecurityService.isLoggedIn()) { 
     render(view: "../homepage") 
     } 
     else { 
     render(view: "../index") 
     } 
    } 

    /** 
    * Show the login page. 
    */ 
    def handleLogin = { 

     if (springSecurityService.isLoggedIn()) { 
     render(view: "../homepage") 
     return 
     } 

     def hashPassd = springSecurityService.encodePassword(params.password) 
     // Find the username 
     def user = Registration.findByEmailAndPassword(params.email,hashPassd) 
     if (!user) { 
     flash.message = "User not found for email: ${params.email}" 
     render(view: "../index") 
     return 
     } else { 
     session.user = user 
     render(view: "../homepage") 
     } 
    } 
} 

は、ここでパスワードをハッシュするbcryptのアルゴリズムを使用するようにGrailsを言って、私のConfig.groovyからの抜粋だとキーイングの回数:

grails.plugins.springsecurity.password.algorithm = 'bcrypt' 
grails.plugins.springsecurity.password.bcrypt.logrounds = 16 

答えて

32

Janが正しい - 設計上のbcryptは、入力文字列ごとに同じハッシュを生成しません。しかし、ハッシュされたパスワードが有効であることを確認する方法があり、関連するパスワードエンコーダに組み込まれています。だからあなたのコントローラ(def passwordEncoder)でpasswordEncoder Beanの依存性注入を追加し、isPasswordValid通話用のパスワードをコードしない

def handleLogin = { 

    if (springSecurityService.isLoggedIn()) { 
     render(view: "../homepage") 
     return 
    } 

    def user = Registration.findByEmail(params.email) 
    if (user && !passwordEncoder.isPasswordValid(user.password, params.password, null)) { 
     user = null 
    } 

    if (!user) { 
     flash.message = "User not found for email: ${params.email}" 
     render(view: "../index") 
     return 
    } 

    session.user = user 
    render(view: "../homepage") 
} 

ノートへの参照を変更 - 平文提出パスワードを渡します。

また、完全に無関係です。ユーザーをセッションに格納することは悪い考えです。 authプリンシパルはすぐに利用でき、必要に応じてユーザを簡単にリロードできるようにユーザIDを格納します(例:User.get(springSecurityService.principal.id))。切断された可能性のある大きなHibernateオブジェクトを格納することは、サーバの唯一のユーザである場合(例えば、mergeなどを使用する必要があります)。

+0

ありがとうBurt。それは働いていました。本当にありがとう、セッションにユーザーを格納することについての感謝の意を表します。私はgrailsに新しく、あなたが提案をすることができれば本当に感謝しています。ベストプラクティスなどに役立つものや....あなたのブログのポストへのリンクかもしれません(私はそれを愛する人の軍隊です...) – adit

13

BCryptハッシュには0123が含まれています結果として、このアルゴリズムは同じ入力に対して異なるハッシュを返す。私にRubyでそれを実演させてください。

> require 'bcrypt' 
> p = BCrypt::Password.create "foobar" 
=> "$2a$10$DopJPvHidYqWVKq.Sdcy5eTF82MvG1btPO.81NUtb/4XjiZa7ctQS" 
> r = BCrypt::Password.create "foobar" 
=> "$2a$10$FTHN0Dechb/IiQuyeEwxaOCSdBss1KcC5fBKDKsj85adOYTLOPQf6" 
> p == "foobar" 
=> true 
> r == "foobar" 
=> true 

結果的に、BCryptは、例のようにユーザーを見つけるために使用することはできません。代わりに明確なフィールドを代わりに使用する必要があります。ユーザーの名前または電子メールアドレス。

+0

これをローカルで実行したい場合は、宝石の名前は何ですか? –

+0

自分の質問に答える、宝石の名前は 'bcrypt-ruby'です。 –

+0

ありがとうございました。ありがとうございます。 – gdgr

関連する問題