Rails – 入力整合性~password_field~bcrypt

概要

bcrypthas_secure_passwordを使ったときの整合性チェックの挙動はtext_fieldの整合性チェックと少し挙動が違う。

has_secure_passwordをモデルに書くと、:passwordに対する整合性を外してもpresenceconfirmationの検証が強制的に行われる。このため意図しないメッセージが重複したり、敢えて空白の入力をスルーしたりしたい場合に、この検証が邪魔になることがある。

この強制的な検証を止めたいときには、has_secure_passwordのオプションにvalidations: falseを指定する(Railsドキュメント)。

手順

設定

  • Gemのbcryptがインストールされていて、Userモデルにhas_secure_passwordが記述されている
  • Userモデルではpassword_digestが準備されている
  • フォームでpasswordの入力欄と再確認用のpassword_confirmationの入力欄の2つを表示する
  • フォーム送信後、2つの入力欄の値が等しいかどうかをバリデーションで確認する

ルーティング

  • usersコントローラーのconfirm_passwordアクションで入力フォームを表示
  • フォームからのPOSTをconfirm_password_processアクションで受け取って処理

モデルの生成

:name属性と:password_digest属性を持つUserモデルを構成する。

マイグレート後

ビュー

名前入力フィールド、パスワード入力フィールドとパスワード確認フィールドを準備する。確認フィールドは入力フィールドの名前に_confirmationポストフィックスを付ける(入力フィールド:passwordに対して:password_confirmation)。

モデル

Userモデルでhas_secure_passwordを設定し、バリデーションではパスワードの整合性のみ検証させる。

コントローラー

confirm_passwordアクションでUserインスタンスを準備してフォームを表示し、confirm_password_processでフォームから受け取ったパラメーターの整合性をチェック。

実行結果

強制的なバリデーションの実行

:password:password_confirmation"aaa""aaa"のときは、valid? == trueでエラーメッセージは空。

パラメーターにはpasswordpassword_confirmationの内容が平文で保持されているが、Userインスタンスにあるのはpassword_digestのみ。

:password:password_confirmationの内容が異なる場合はvalid? == falseで、エラーメッセージは同じ"doesn't match ..."が2回現れている。

:passwordに何か入力して:password_confirmationを空欄にしても同じ結果になる。

:passwordを空欄にした場合、:password_confirmationの内容の有無に関わらずvalid? == falseで、エラーメッセージは"can't be blank"が2回、"doesn't match ..."が1回発生。

また、:password:password_confirmation両方を空白のままにした時も同じ結果になる。

:password:password_confirmationの内容がそれぞれA、B、空白の組み合わせに対する結果をまとめると以下のようになり、検証結果が不適切な場合の全てでメッセージが2つ出されている。

pass\conf A B 空白
A true
[]
false
“doesn’t match”
“doesn’t match”
false
“doesn’t match”
“doesn’t match”
B false
“doesn’t match”
“doesn’t match”
true
[]
false
“doesn’t match”
“doesn’t match”
空白 false
“can’t be blank”
“doesn’t match”
false
“can’t be blank”
“doesn’t match”
false
“can’t be blank”
“doesn’t match”

bcryptによるバリデーションの抑止

ここで、has_secure_passwordのオプションでバリデーションを無効にしてみる。

これで先と同じ票のように実行してみる。

pass\conf A B 空白
A true
[]
false
“doesn’t match”
false
“doesn’t match”
B false
“doesn’t match”
true
[]
false
“doesn’t match”
空白 false
“doesn’t match”
false
“doesn’t match”
false
“doesn’t match”

validatesの方でpresenceのチェックをせずconfirmationだけをチェックしているので、空白の場合でも"can't be blank"は発生していない。

また、bcrypt側の検証を止めているので、"doesn't match ..."のメッセージもvalidatesconfirmによるものだけになっている。

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です