【Devise】パスワードリセット機能実装手順
はじめに
こんにちは!大ちゃんの駆け出し技術ブログです。
deviseでユーザ登録機能とログイン機能の実装に関する記事はたくさんありますが、deviseでパスワードリセット機能を実装したかったのですが思ったよりも記事の数が少なかったので自分で記事にしてみました。何かのお役に立てればと思います。なお、ログイン機能とユーザ登録機能については既にdeviseで実装済みであることを想定しています。
基本設定
まずはuser.rb
にrecoverable
を追加します。
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :omniauthable
また、deviseのマイグレーションファイルでrecoverable
の箇所をコメントアウトしていた方はコメントアウトを外してuserのカラムに加えてください。
## Recoverable t.string :reset_password_token t.datetime :reset_password_sent_at t.boolean :allow_password_change, :default => false
次にパスワードリセットメール送信画面のレイアウトを整えます。自分はtailwindとslimを使っているので以下の部分はtaiwindを使っている方のみコピペしてください。
/ app/views/users/passwords/new.html.slim .flex.flex-col.items-center.justify-center.h-screen.select-none .flex.flex-col.-mt-32.bg-brown-50.px-6.sm:px-6.md:px-8.lg:px-10.py-8.rounded-xl.shadow-2xl.w-full.max-w-md.border-l-4.border-brown-600 .text-xl.top-sub-title.text-center | パスワードリセット .mt-10 = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| = render "users/shared/error_messages", resource: resource .relative.w-full.mb-3 = f.label :email, class: 'form-label-basic-block' = f.email_field :email, autofocus: true, autocomplete: "email", class: "input-form-basic-block" .text-center.mt-6 .actions = f.submit "リセットメールを送信", class: "p-3 rounded-lg bg-brown-600 outline-none text-white shadow w-auto justify-center focus:bg-brown-700 hover:bg-brown-500" = render "shared/signup_links"
パスワードリセットを実際に行う画面のレイアウトはリセットトークンがないと遷移できない仕様となっているため見ることはできませんが、レイアウトを整えておきます。
.flex.flex-col.items-center.justify-center.h-screen.select-none .flex.flex-col.-mt-32.bg-brown-50.px-6.sm:px-6.md:px-8.lg:px-10.py-8.rounded-xl.shadow-2xl.w-full.max-w-md.border-l-4.border-brown-600 .text-xl.top-sub-title.text-center | パスワード変更 .mt-10 = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| = render "users/shared/error_messages", resource: resource = f.hidden_field :reset_password_token .relative.w-full.mb-3 = f.label :password, class: 'form-label-basic-block' - if @minimum_password_length em | ( = @minimum_password_length | 文字以上で入力してね) = f.password_field :password, autofocus: true, autocomplete: "new-password", class: "input-form-basic-block" .relative.w-full.mb-3 = f.label :password_confirmation, class: 'form-label-basic-block' = f.password_field :password_confirmation, autofocus: true, autocomplete: "new-password", class: "input-form-basic-block" .text-center.mt-6 .actions = f.submit "パスワードをリセット!", class: "p-3 rounded-lg bg-brown-600 outline-none text-white shadow w-auto justify-center focus:bg-brown-700 hover:bg-brown-500" = render "shared/signup_links"
パスワードの変更メールを作成します。edit_user_password_url
で変更画面への遷移をするようにします。reset_password_token
がないと編集画面に遷移できないため、必ずリンクにreset_password_token
を含めてください。
p = @resource.email | 様 p | ログインのパスワードリセットの申請を受け付けました。 p | パスワードの再設定をご希望の場合は、以下のリンクをクリックし 新しいパスワードをご登録ください。 p = link_to 'パスワード変更', edit_user_password_url(@resource, reset_password_token: @token) p | ※パスワードリセットの申請に心当たりがない場合は、以降の対応は不要となります。 p | ※リンクの有効期限は24時間です。
ちなみにパスワードリセットのリンクの有効期限はデフォルトで6時間となっていますが、devise.rb
で変更可能です。
# Time interval you can reset your password with a reset password key. # Don't put a too small interval or your users won't have the time to # change their passwords. config.reset_password_within = 24.hours
これで基本設定は完了です。
メールアドレスの作成
開発アプリ用のメールアドレスを作成しましょう。基本的には以下の英語文献の記事を参照すれば実装できます。
Getting Devise to send reset password link
gmailのアカウント作成をします。ユーザ名などはお任せします。使用されていないgmailアドレスを登録してください。
登録後、アカウントの設定でhttps://myaccount.google.com/lesssecureappsにアクセスします。ここで安全性の低いアプリのアクセスを有効にすることで開発環境からのアクセスを許可します。
環境変数を管理するdotenv
をインストールします。
gem 'dotenv-rails'
.env
ファイルを作成し、そこに登録したメールアドレスとパスワードを記載します。
GMAIL_USERNAME = hoge@gmail.com GMAIL_PASSWORD = hogehogehogehoge
.env
ファイルはコミットされないようにgitignoreで設定します。
# .gitignore
.env
development.rb
で以下の設定を行います。
# config/environments/development.rb config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } # mail setting config.action_mailer.raise_delivery_errors = true config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :address => "smtp.gmail.com", :port => 587, :user_name => ENV["GMAIL_USERNAME"] , :password => ENV["GMAIL_PASSWORD"] , :authentication => :plain, :enable_starttls_auto => true }
これによりメールの送信が登録したアドレスで行えるようになりました。
実装確認
まずパスワードリセット画面で開発環境で実際にユーザ登録済みのメールアドレスを入力してください。完了したら送信ボタンを押します。
するとターミナル上でメール送信の処理が行われていることがわかります。
Devise::Mailer#reset_password_instructions: processed outbound mail in 19.0ms Delivered mail 60a598b8236ca_b8513fd849f29f48480ad (3861.7ms) Date: Thu, 20 May 2021 08:01:12 +0900 From: please-change-me-at-config-initializers-devise@example.com Reply-To: please-change-me-at-config-initializers-devise@example.com To: hoge@gmail.com Message-ID: <60a598b8236ca_b8513fd849f29f48480ad.mail> Subject: =?UTF-8?Q?=E3=83=91=E3=82=B9=E3=83=AF=E3=83=BC=E3=83=89=E3=81=AE=E5=86=8D=E8=A8=AD=E5=AE=9A=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6?= Mime-Version: 1.0 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: base64
送信したメールアドレスを確認しましょう。実際にメールが届いていることが確認できます。反対に、登録したgmailアドレスの方を確認すると、送信済みボックスに同様のメールが送られていることが確認できます。
パスワードの変更リンクをクリックするとパスワード変更画面に遷移します。
ここで新しいパスワードを入力することでパスワードのリセット及びサインインを同時に行ってくれます。deviseのよしなにやってくれている機能は本当にすごいですね!