【Rails】 Authlogicでパスワードリマインダーを実装する

ユーザーがパスワードを忘れてしまった際にパスワードを再設定できる機能を実装してみます。

パスワードリマインダーには色々な実装方法がありますが、
今回は登録されているメールアドレスにパスワード再設定用のURLを送信する方法で実装します。

・Authlogicの導入については以下ページで説明しています
【Rails】 Authlogicでユーザー認証機能

まずはユーザーが入力したメールアドレスにパスワード再設定用のURLを送信するところを実装します

必要なカラムを追加する

$ rails g migration AddPerishableTokenToUsers
# db/migrate/20130622071854_add_perishable_token_to_users.rb

class AddPerishableTokenToUsers < ActiveRecord::Migration
  def change
    add_column :users, :perishable_token, :string
  end
end
$ rake db:migrate

パスワードリマインダー用のコントローラーを作成する

$ rails g controller password_resets

ルーティングを設定する

# config/routes.rb

...
resource :password_resets, only: [:new, :edit, :create, :update]
...

アクションを定義する

# app/controllers/password_resets_controller.rb

class PasswordResetsController < ApplicationController
  # 認証用の処理はスキップする
  skip_before_action :require_login

  # GET /password_resets/new
  def new
  end

  # POST /password_resets
  def create
    user = User.find_by(email: params[:email])

    if user
      user.deliver_password_reset_instructions!
      # 遷移先は適宜変更してください
      redirect_to login_url
    else
      render :new
    end
  end
end

トークンのリセットとメール送信処理を呼び出すメソッドを定義する

# app/models/user.rb

class User < ActiveRecord::Base
  def deliver_password_reset_instructions!
    reset_perishable_token!
    NotifierMailer.password_reset_instructions(self).deliver
  end
end

ビューを作成する

# app/views/password_resets/new.html.erb

<h2>パスワード再設定</h2>

<%= form_tag password_resets_path do %>
  <p class="field">
    <%= label_tag :email, "メールアドレス" %>
    <%= text_field_tag :email %>
  </p>

  <%= submit_tag "送信" %>
<% end %>
# app/views/layouts/application.html.erb

...
<%= link_to "パスワード再設定", new_password_resets_path %>
...

ActionMailerでメール送信処理を実装する

$ rails g mailer NotifierMailer password_reset_instructions
# app/mailers/notifier_mailer.rb

class NotifierMailer < ActionMailer::Base
  default from: "from@example.com"

  def password_reset_instructions(user)
    @url = edit_password_resets_url(token: user.perishable_token)

    mail to: user.email,
         subject: "パスワードの再設定"
  end
end

メールの本文

# app/views/notifier_mailer/password_reset_instructions.text.erb

<%= @url %>

Gmailでメールを送信するための設定

# config/environments/development.rb

# メール送信時のエラーをログに出力する設定
config.action_mailer.raise_delivery_errors = true

config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address: "smtp.gmail.com",
  port: 587,
  domain: 'example.com',
  user_name: "GmailのID",
  password: "Gmailのパスワード",
  authentication: 'plain',
  enable_starttls_aut: true,
}

次にパスワード再設定用のURLがクリックされた後の処理を実装します

アクションを定義する

class PasswordResetsController < ApplicationController
  before_filter :load_user_using_perishable_token, only: [:edit, :update]

  # GET /password_resets/edit
  def edit
  end

  # PATCH/PUT /password_resets
  def update
    @user.attributes = user_params
    if @user.save
      # 遷移先は適宜変更してください
      redirect_to root_url
    else
      render :edit
    end
  end
 
  private
    def load_user_using_perishable_token
      @user = User.find_using_perishable_token(params[:token])
      unless @user
        # 遷移先は適宜変更してください
        redirect_to login_url
      end
    end

    def user_params
      params.require(:user).permit(:password, :password_confirmation)
    end
end

パスワードを変更するビューを作成する

# app/views/password_resets/edit.html.erb

<h1>パスワードの変更</h1>

<%= form_for @user, url: password_resets_path(token: @user.perishable_token) do |f| %>
  <p class="field">
    <%= f.label :password %>
    <%= f.password_field :password %>
  </p>

  <p class="field">
    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation %>
  </p>

  <%= f.submit "更新する" %>
<% end %>

以上です。


・参考にしたサイト
http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic/