らくだ🐫にもできるRailsチュートリアル|12.1

12章でやること
パスワードを忘れた時に再設定できるようにする仕組みを作る
見本は本文参照の事
11章ですでにパスワード再設定用のメーラーが生成されているので、そこにリソースとデータモデルを追加してパスワードの再設定を実装していく。
全体の流れはこちら

  1. ユーザーがパスワードの再設定をリクエストすると、ユーザーが送信したメールアドレスをキーにしてデータベースからユーザーを見つける
  2. 該当のメールアドレスがデータベースにある場合は、再設定用トークンとそれに対応するリセットダイジェストを生成する
  3. 再設定用ダイジェストはデータベースに保存しておき、再設定用トークンはメールアドレスと一緒に、ユーザーに送信する有効化用メールのリンクに仕込んでおく
  4. ユーザーがメールのリンクをクリックしたら、メールアドレスをキーとしてユーザーを探し、データベース内に保存しておいた再設定用ダイジェストと比較する (トークンを認証する)
  5. 認証に成功したら、パスワード変更用のフォームをユーザーに表示する

12.1 PasswordResetsリソース

branchを作ってから作業開始!

アカウント有効化リソースの際はeditアクションだけを使ったけど、
再設定では再設定用のフォームが必要→対応するviewを描写する必要がある→それぞれのアクションが必要
などから、RESTfulなルーティングが必要になる

12.1.1 PasswordResetsコントローラ

早速コントローラを生成

今回はビューも扱うので、newアクションとeditアクションも一緒に生成している点に注意してください。

コントローラの単体テストをする代わりに、前章(11.3.3)から統合テストでカバーしていくため

パスワード再設定用リソースを追加

新しいパスワードを再設定するためのフォームとUserモデル内のパスワードを変更するためのフォームが必要なので↓下記

パスワード再設定画面へのリンクを追加

ログインフォームの「パスワード」の横にリンクが来るように設置

演習

  1. この時点で、テストスイートが greenになっていることを確認してみましょう。
  2. 表 12.1の名前付きルートでは、_pathではなく_urlを使うように記してあります。なぜでしょうか? 考えてみましょう。ヒント: アカウント有効化で行った演習 (11.1.1.1) と同じ理由です。
  1. GREEN
  2. ページ内の相対リンクからではなく、メール本文の絶対リンクからリクエストを送るため

12.1.2 新しいパスワードの設定

パスワードの再設定もアカウント有効化の場合と同じく、トークン用の仮想的な属性とそれに対応するダイジェストを用意する
何度も言われているように、トークンをハッシュ化せずに平文でDBに保存するとセキュリティ上大問題となる!

攻撃者がユーザーのメールアドレスにパスワード再設定のリクエストを送信し、このメールと盗んだトークンを組み合わせて攻撃者がパスワード再設定リンクを開けば、アカウントを奪い取ることができてしまう、ということです。

→パスワードの再設定では!必ず!ダイジェストを使用する!!
また、再設定用のリンクはなるべく短時間で期限切れするようにしたい(本文には数時間とあるけど、30分以内に~とかよく見るよね)
→再設定用のメール送信時刻も記録する必要がある

パスワード再設定用のカラムをUserモデルに追加

上記に基づいてreset_digest属性とreset_sent_at属性をUserモデルに追加する

パスワード再設定用のカラムを追加したUserモデル→RailsTutorial本文

パスワード再設定画面を作成

ログインフォームのコードを参考にパスワードを再設定するためのフォームを作成する

演習

  1. リスト 12.4のform_forメソッドでは、なぜ@password_resetではなく:password_resetを使っているのでしょうか? 考えてみてください。
  1. password_resetはpassword_resetモデルがない→インスタンス変数に相当するものがない→form_forヘルパーに追加の情報を独自に渡す必要がある(渡すオブジェクトがないのでリソースの名前とそれに対応するURLを具体的に指定する必要がある)

12.1.3 createアクションでパスワード再設定

createアクションの動き

フォームから送信を行なった後、メールアドレスをキーとしてユーザーをデータベースから見つけ、パスワード再設定用トークンと送信時のタイムスタンプでデータベースの属性を更新する必要があります。それに続いてルートURLにリダイレクトし、フラッシュメッセージをユーザーに表示します。送信が無効の場合は、ログイン (リスト 8.11) と同様にnewページを出力してflash.nowメッセージを表示します。変更の結果をリスト 12.5に示します。

Userモデルにメソッドを追加

現状、無効なメールアドレスを入力した場合は正常に作動するけど
有効なメールアドレスを入力した場合はエラーになる
(パスワード再設定のメイラーメソッドを定義する必要があるので次の章でやるっぽい)

演習

  1. 試しに有効なメールアドレスをフォームから送信してみましょう (図 12.6)。どんなエラーメッセージが表示されたでしょうか?
  2. コンソールに移り、先ほどの演習課題で送信した結果、(エラーと表示されてはいるものの) 該当するuserオブジェクトにはreset_digestとreset_sent_atがあることを確認してみましょう。また、それぞれの値はどのようになっていますか?

1.

引数のエラー→PasswordResetsController#create→問題のあるソース(app/mailers/user_mailer.rb:10:in `password_reset’)
2.

まとめとか感想

フォームについて、わけ!わか!らん!となってかなり遡って見直したりしました
Railsチュートリアル内の話だし、実際はもっと違うのかもしれないとかも思いつつだけど
自力でひとまず納得できたので良しとしましょうそうしましょう!
「@password_resetではなく:password_resetを使っているのでしょうか? 」の回答にモヤっとしたものが残るけど進めていくうちにわかるかもしれないのでとりあえずほかにメモった。
あとアレ。タイポの癖ってあるよね😢

らくだ🐫にもできるRailsチュートリアルとは

「ド」が付く素人のらくだ🐫が勉強するRailsチュートリアルの学習記録です。
自分用に記録していますが、お役に立つことがあれば幸いです。

調べたとはいえらくだ🐫なりの解釈や説明が含まれます。間違っている部分もあるかと思います。そんな所は教えて頂けますと幸いなのですが、このブログにはコメント機能がありません💧お手数おかけしますがTwitterなどでご連絡いただければ幸いです