LoginSignup
45
63

More than 5 years have passed since last update.

railsのdeviseを使ってユーザー認証機能を実装する一連の流れの備忘録

Last updated at Posted at 2017-09-17

deviseとは

この記事では、railsでのdeviseを使ったログイン認証機能の実装について、備忘録として書き残すことにする。
なお、下記のページを参考にさせていただきました。

とりあえず動くようにする

はじめにgemをインストール。

Gemfile
# 以下を追加
gem 'devise'
bundle install

一通り機能をインストールする。

rails g devise:install #全体のインストール
rails g devise user #ユーザーモデルを作成
rake db:migrate #userテーブルを作成
rails g devise:views #ビューの作成

なお、devise:installした時に、いくつか指示が出ている。まず下記をconfigファイルに追記。自分の環境では大体30行目くらいに入れました。

/config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

この時点でルーティングまで自動で行われているが、ルートの設定ができていることを確認しておく。

/config/routes.rb
devise_for :users #自動で挿入されている
root 'blogs#index' #それぞれのパスに設定

下記のflashメッセージも追加。とりあえずbodyの真下としておく。

/app/views/layouts/application.html.erb
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

望み通りの仕様にカスタマイズする

このままだとまだまだ実用に程遠いので、カスタマイズしていく。
ユーザー認証にすると同時に自動的にやっておいた方がいいよねこれっていう機能は割と多いように思う。
本記事の中では、デザインの部分(CSS周り)はとりあえず無視します。

ユーザーのログイン状態を判定し、ルーティング先を変更

たいていの場合、ページに飛んできた人がすでにログイン状態かどうかを判定して、
- ログイン状態であればリクエストのコンテンツを表示
- ログイン状態でなければログインページ、もしくはサインアップのページに飛ぶ
という操作となると思う。それの実装。と言ってもdeviseにすでにそれ用のヘルパーが定義されている。

/app/controllers/application_controller.rb
before_action :authenticate_user! #protect_from_forgery with: :exceptionより後におく。

アプリ全体の仕様にしたかったのでapplicationに記載。そうでなければ、それぞれのコントローラに仕込む。

実装の確認のために、ログアウトのリンクを仕込んでおく。

/app/views/layouts/application.html.erb
#以下を適当なところに追記
<% if user_signed_in? %>
<p><%= link_to "ログアウト", destroy_user_session_path, method: :delete %></p>
<% end %>

これでログイン時はリクエストしたページへ通し、ログオフ時はログイン画面に弾くようになった。そしてそれを確認。

メール認証

サインアップしたユーザーアカウントは、一旦仮登録としてメールを飛ばし、返信を持って本登録とするあれ。
ステップは次の通り。

Userモデルにconfirmableを追加。これで各種認証時に「確認作業」が定義できるようになる。Eメール認証はそのやり方のうちの一つ、くらいで認識している。

/app/models/user.rb
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable #最後のやつを追加

Userテーブルに確認にまつわる項目を追加しなければいけないようだ。マイグレーションファイルを作成。

rails g migration add_confirmable_to_devise

マイグレーションファイルを次のようにする。ここは、上記参考ページのままコピペ。reconfirmbleも設定したい人は、コメント外した方がいい行がいくつかある。関係ないのでこのままでいく。

/db/migrate/yyyymmddxxxxxx_add_confirmable_to_devise.rb
class AddConfirmableToDevise < ActiveRecord::Migration[5.1]
  # Note: You can't use change, as User.update_all will fail in the down migration
  def up
    add_column :users, :confirmation_token, :string
    add_column :users, :confirmed_at, :datetime
    add_column :users, :confirmation_sent_at, :datetime
    # add_column :users, :unconfirmed_email, :string # Only if using reconfirmable
    add_index :users, :confirmation_token, unique: true
    # User.reset_column_information # Need for some types of updates, but not for update_all.
    # To avoid a short time window between running the migration and updating all existing
    # users as confirmed, do the following
    User.all.update_all confirmed_at: DateTime.now
    # All existing user accounts should be able to log in after this.
  end

  def down
    remove_columns :users, :confirmation_token, :confirmed_at, :confirmation_sent_at
    # remove_columns :users, :unconfirmed_email # Only if using reconfirmable
  end
end
rake db:migrate

これで、Eメール送信のための設定は済んだわけですが、肝心のSMTPサーバの設定が必要。うっかりgithubにアップしたくはないから、letter-opener_webを使うことにする。まずはgemをインストール。

Gemfile
group :development do #開発環境のみ
  gem 'letter_opener_web'
end
bundle install

以下をルーティング設定に追加。

/config/routes.rb
if Rails.env.development? #開発環境の場合
  mount LetterOpenerWeb::Engine, at: "/letter_opener"
end

メールの送信にletter_opener_webを使用する。

/config/environments/development.rb
#以下を追記(config.action_mailer.default_url_optionsの直下あたりがしっくりくるか)
config.action_mailer.delivery_method = :letter_opener_web

これでメール送信の設定は全て終了。メール認証が実装できていることを確認できると思いきや、エラーが発生した。原因はテーブルでコメントのままだった下記の2行のようだ。アンコメントして、migrationし直したらEメール認証できるようになった。

/db/migrate/yyyymmddxxxxxx_add_confirmable_to_devise.rb
class AddConfirmableToDevise < ActiveRecord::Migration[5.1]
  # Note: You can't use change, as User.update_all will fail in the down migration
  def up
    #(省略)
    add_column :users, :unconfirmed_email, :string # Only if using reconfirmable
    #(省略)
  end

  def down
    #(省略)
    remove_columns :users, :unconfirmed_email # Only if using reconfirmable
  end
end

管理者権限の設定

複数のユーザーがサービスを用いる場合、普通は管理者権限を設定し、特殊な操作は管理者のみ実行可としておく。

rails generate migration add_admin_to_users admin:boolean
/db/migrate/yyyymmddxxxxxx_add_confirmable_to_devise.rb
add_column :users, :admin, :boolean, default: false

デフォルト値は当然のごとくfalse。trueだと基本みんな管理者になってしまう。

あとは次のように管理者しかできないアクションを定義してやれば良い。

if current_user.admin? # current_userメソッドがnilとなるページも考慮し、current_user.try(:admin?)でもいいらしい
#do something
end

終わりに

ということで、deviseの導入によるユーザー認証機能とそれに伴う設定をいくつかやりましたが、ルーティングの設定などは細かく定義できますし、facebookアカウントでの認証などの機能もありますね。やろうと思えば山積みです。
もっと簡単にできるとかそもそも間違っているとかがありましたら、ご指摘願えれば幸いです。

45
63
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
63