0

UserSpringSecurityコアプラグインを介して作成されたドメインエンティティにGraisでパスワード検証を実装しようとしています。エンティティに次のコードを追加しました。

class User {
  // Added by the spring security core plugin
  String password
  // Added by me
  String passwordConfirm

  static constraints = {
    passwordConfirm blank:false, validator: { val, obj ->
       if (!obj.password.equals(obj.passwordConfirm)) {
           return "user.password.confirmation.error"
       }
    }
  }

  // other methods...
}

passwordが一致しない場合、バリデーターは期待どおりに機能しpasswordConfirmます。ただし、バリデーターが正常に渡され、インスタンスが永続化されようとしている場合、次の例外が発生します。

org.hibernate.AssertionFailure: null id in com.test.User entry (don't flush the Session after an exception occurs)

    at com.shopify.RegistrationController$_closure2.doCall(RegistrationController.groovy:14)

    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

    at java.lang.Thread.run(Thread.java:680)

を使用してエンティティを永続化していますuser.save(flush: true)

検証を削除すると、インスタンスはデータベースに正常に永続化されるため、バリデーターに何か問題があるはずだと思います。何が悪いのかについて何か提案はありますか?Grailsバージョン2.0.4を使用しています。

編集:私が私のエンティティを保存する部分は次のとおりです:

def register = {    
    def user = new User(params)
    if (!user.save(flush:true, failOnError:true)) {
        render view: 'register', model: [userInstance: user]
    } else {
        render view: 'success'
    }
}

編集:さて、私は春のセキュリティコアによって挿入された次のコードをコメントアウトすることによってこの仕事をすることができました:

def beforeInsert() {
    // encodePassword()
}

def beforeUpdate() {
    // if (isDirty('password')) {
    //  encodePassword()
    // }
}

現時点では、なぜこれが発生するのかわかりませんが、これを確認します。それまでの間、誰かがこれについて何か情報を持っているなら、私はそれを私と共有することに本当に興味があります。

編集:この関連するバグレポートを見つけました:http://jira.grails.org/browse/GRAILS-9083

4

1 に答える 1

0

ユーザーが挿入される前にパスワードがハッシュされるため、検証は失敗します。したがって、パスワードは passwordConfirm と等しくなくなり、検証エラーがトリガーされます。

ここにあなたがしていることがあります:

save() の前:

def password = 1234
def passwordConfirm = 1234
password == passwordConfirm  validation passes

.save() 中。挿入がトリガーされる前:

def password gets hashed:  
def password = 1JO@J$O!@J$P!O@$JP!@O$J!@O$J!@
def passwordConfirm = 1234
password != passwordConfirm validation fails

ドメインから encodePassword() を削除した後:

def password = 1234
def passwordConfirm = 1234
password == passwordConfirm  validation passes but now you have your password in plain texts inside your DB, you should never do this for security reasons.

簡単な修正は、ドメインオブジェクト自体ではなく、別のコマンドオブジェクトで検証を行うことです.passwordConfirmはドメインクラスにあってはなりません。

例: Spring Security UI のsourceを見て、コマンド オブジェクトを使用してコントローラーで検証を処理する方法を確認してください。

于 2012-10-02T21:28:03.733 に答える