Railsでdeviseによる認証

By | 2018/04/09

認証はセキュリティを考えなければなんとでもなりますが、そこは避けては通れないのでライブラリに頼ったほうが良いということで割とメジャーそうなdeviseを触ってみました。基本的なMVCの作り方はわかるものとしてdeviseに関する部分にフォーカスします。ここではコントローラー名はLoginTestとします。

まず必要な設定とインストールをします。

Gemfileに下記を追加

gem 'devise'

そしてインストール

>bundle install
>rails generate devise:install
Running via Spring preloader in process 13350
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml

deviseによるgenerateができるのでこれでテーブル作成を作成します。モデルのgenerateに近い記述ですね。ここではaccountとします。あとマイグレーション。

>rails generate devise account
Running via Spring preloader in process 20187
      invoke  active_record
      create    db/migrate/20180327082026_devise_create_accounts.rb
      create    app/models/account.rb
      invoke    test_unit
      create      test/models/account_test.rb
      create      test/fixtures/accounts.yml
      insert    app/models/account.rb
       route  devise_for :accounts
>rails db:migrate

主なファイルは以下のようなコードが生成されます。
account.rb

class Account < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

routes.rb

Rails.application.routes.draw do
  devise_for :accounts

migrate/xxxx_devise_create_accounts.rb

# frozen_string_literal: true

class DeviseCreateAccounts < ActiveRecord::Migration[5.1]
  def change
    create_table :accounts do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :accounts, :email,                unique: true
    add_index :accounts, :reset_password_token, unique: true
    # add_index :accounts, :confirmation_token,   unique: true
    # add_index :accounts, :unlock_token,         unique: true
  end
end

ログイン処理

まず表示部分を用意します。ログイン画面に行くためのページを用意。
view/login_test/index.html.erb

<!-- log in -->
<div><%= link_to 'Log in! &gt;&gt;'.html_safe, {action:'login'} %></div>

ログインページへ行くためにloginアクションへのリンクを作ります。そのためloginページも作っておきます。
view/login_test/login.html.erb

<h1><%= @account.email %></h1>
<%= @msg %>

ログインしたら@accountと@msgを渡すようにしておきます。

続いてコントローラーを用意します。ログインページに行く用とログイン画面用のアクションを用意します。
ここで重要なのがbefore_actionとして認証チェックを挟むコードを入れることです。下のコードだとloginアクションが呼び出された時認証済みかチェックしてくれて、認証されていないときは勝手に認証ページ(sign_up)へ飛ばしてくれます。
authenticate_accountはdeviseでaccountを作った時に作られます。

controllers/login_test_controller.rb

class LoginTestController < ApplicationController

  # check authentification
  before_action :authenticate_account!, only: :login

  def index
  end

  def login
    @account = current_account
    @msg = 'login date: ' + @account.current_sign_in_at.to_s
  end
end

最後にルーティング

  get 'login_test/index'
  get 'login_test/login'

以上で完了です。login_test/indexからloginアクションをクリックすると最初はsign_upページへ飛ぶはずです。最初はアカウントがないので下の方にあるsignupボタンを押して1つアカウントを追加する必要があります。

ログアウト処理

ログインしたのでログアウトも必要です。このためトップページであるindexにログアウト用のリンクを追加します。
こちらはページを用意しません。
重要なのはsign_out用のパスがすでに設定されているのでこれを使いdeleteメソッドでアクセスしてあげる必要があります。
view/login_test/index.html.erb

<!-- log in -->
<div><%= link_to 'Log in! &gt;&gt;'.html_safe, {action:'login'} %></div>
<!-- log out -->
<div><%= link_to "Sign out &gt;&gt;".html_safe, destroy_account_session_path, method: :delete %></div>

このリンクを押せばログアウトできます。

ログインページのデザイン

deviseの画面は全然簡素なものです。実際のウェブサービスではまず使えないのでカスタマイズしてやる必要があります。
そのための方法がある程度用意されています。以下のコマンドでviewが生成されるのでこれを直します。

>rails generate devise:views
Running via Spring preloader in process 34454
invoke Devise::Generators::SharedViewsGenerator
create app/views/devise/shared
create app/views/devise/shared/_links.html.erb
invoke form_for
create app/views/devise/confirmations
create app/views/devise/confirmations/new.html.erb
create app/views/devise/passwords
create app/views/devise/passwords/edit.html.erb
create app/views/devise/passwords/new.html.erb
create app/views/devise/registrations
create app/views/devise/registrations/edit.html.erb
create app/views/devise/registrations/new.html.erb
create app/views/devise/sessions
create app/views/devise/sessions/new.html.erb
create app/views/devise/unlocks
create app/views/devise/unlocks/new.html.erb
invoke erb
create app/views/devise/mailer
create app/views/devise/mailer/confirmation_instructions.html.erb
create app/views/devise/mailer/email_changed.html.erb
create app/views/devise/mailer/password_change.html.erb
create app/views/devise/mailer/reset_password_instructions.html.erb
create app/views/devise/mailer/unlock_instructions.html.erb

views/devise以下にたくさんファイルが作られるので多少面倒ですががんばって見栄えのよい画面を作りましょう。


コメントを残す

メールアドレスが公開されることはありません。