新しいgrailsプロジェクトに登録機能を追加しました。テストのために、メールとパスワードを入力して登録しました。データベースに保存する前にパスワードをハッシュするためにbcryptアルゴリズムを使用しています。
ただし、登録時に指定したのと同じメールアドレスとパスワードでログインしようとすると、ログインに失敗します。アプリケーションをデバッグしましたが、データベースから既にハッシュされているものと比較しようとすると、同じパスワードに対して生成されるハッシュが異なり、ログインが失敗することがわかりました(Registration.findByEmailAndPassword(params.email、 hashPassd)がLoginController.groovyでnull)を返します。
これが私のドメインクラス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")
}
}
}
これは私のConfig.groovyからのスニペットで、brailアルゴリズムを使用してパスワードとハッシュのラウンド数をハッシュするようにgrailsに指示しています。
grails.plugins.springsecurity.password.algorithm = 'bcrypt'
grails.plugins.springsecurity.password.bcrypt.logrounds = 16
Janは正しい-設計によるbcryptは、各入力文字列に対して同じハッシュを生成しません。しかし、ハッシュされたパスワードが有効であることを確認する方法があり、関連するパスワードエンコーダーに組み込まれています。そのため、コントローラ(_def passwordEncoder
_)でpasswordEncoder
Beanの依存関係注入を追加し、ルックアップを次のように変更します
_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")
}
_
isPasswordValid
呼び出しのパスワードはエンコードしないことに注意してください。クリアテキストで送信されたパスワードを渡します。
また、完全に無関係です。ユーザーをセッションに保存することはお勧めできません。 authプリンシパルはすぐに利用でき、必要に応じてユーザーを簡単に再読み込みできるようにユーザーIDを保存します(例:User.get(springSecurityService.principal.id)
。切断された潜在的に大きなHibernateオブジェクトを保存すると、開発者モードでのみ、あなたのサーバー、しかしメモリのかなりの浪費になる可能性があり、切断されているオブジェクトを回避することを強制します(例えばmerge
を使用する必要があるなど)。
BCryptハッシュには salt が含まれているため、このアルゴリズムは同じ入力に対して異なるハッシュを返します。 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は、例に示されている方法でユーザーを見つけるために使用することはできません。代わりに明確なフィールドを代わりに使用する必要があります。ユーザーの名前または電子メールアドレス。