DK’s diary

プログラミング初学者による発信

*devise使用:ログイン済みのユーザーのみをアクセス可能にする設定

遷移先へのボタンを隠すだけではダメ

大部分のアプリケーションでは会員登録機能がついており、登録してログイン済みでなければそのアプリのメイン機能を使用できないようになっているかと思います。

私が作成しているアプリでもログイン済みか否かによってナビバーの表示を変更し、ログイン済みでなければ先に進めないようにしてあります。

ログイン前↓
f:id:dkdkdk3:20200611215751p:plain



ログイン後↓
f:id:dkdkdk3:20200611220112p:plain



これはif文で分岐させることで実装できます。
deviseのヘルパーメソッドであるuser_signed_in?を用いてユーザーがログイン済みかどうかを判定します。

<% if user_signed_in? %>
  <li class="nav-item">
    <%= link_to "#{current_user.username}さんのマイページ", user_path(current_user.id) %>
  </li>
  <li class="nav-item">
    <%= link_to "助っ人を探す", maps_path %>
  </li>
  <li class="nav-item">
    <%= link_to "チャット", "#" %>
  </li>
  <li class="nav-item">
    <%= link_to "ログアウト", destroy_user_session_path, method: "delete" %>
  </li>
<% else %>
  <li class="nav-item">
    <%= link_to "会員登録", new_user_registration_path %>
  </li>
  <li class="nav-item">
    <%= link_to "ログイン", new_user_session_path %>
  </li>
<% end %>


未ログインではボタンそのものが無いのでアクセスできないと思いきや、
実はURLを直打ちすることで飛べてしまいます。

先程の私のアプリの例で、未ログインのまま "助っ人を探す" のページに飛んでみます!
f:id:dkdkdk3:20200611223235p:plain


直接URLを打ち込んでと。。。

f:id:dkdkdk3:20200611224014p:plain

飛べてしまいました。
添付画像の右上を見てもらえばわかりますが未ログインのままです。
対策をしましょう!!


before_actionで対策

当該のコントローラにおいてすべてのアクションで実行の前に共通の処理を行いたいときに、before_actionを使用すると全てのアクションが実行される前に指定したメソッドを呼び出すことができます。

つまり上記の例でいうと、
マップを表示させているmapsコントローラーはユーザーがログイン済みでないとアクションが実行されないように設定すれば良いのです。

app > controllers > maps_controller.rb

class MapsController < ApplicationController
  before_action :login_check

  # 省略

  private
  def login_check
    unless user_signed_in?
      redirect_to root_path
    end
  end
end

before_actionでlogin_checkというメソッドを定義します。

メソッドを書くのはprivate以下です。
上記のナビバーと同様にuser_signed_in?を使用します。
ユーザーがログインしてなければ "root_path"(TOPページ)にリダイレクトするようにしました。
これで未ログインのユーザーが直打ちで侵入することは防げました。

が、しかし・・・
もっと簡単な方法がありました。

deviseのヘルパーメソッドの一つに
before_action :authenticate_user!
があり、

app > controllers > maps_controller.rb

# authenticate_user!適用前
class MapsController < ApplicationController
  before_action :login_check

    # 省略

  private
  def login_check
    unless user_signed_in?
      redirect_to root_path
    end
  end
end


#authenticate_user!適用後
class MapsController < ApplicationController
  before_action :authenticate_user!

    # 省略

end

上記のように1行で済みます!
会員登録にdeviseを使用していたら断然こっちですね!

ちなみに
デフォルトの設定ではログインしていない場合、ログイン画面に遷移する仕様になっています。
変更したい場合は下記のように上書きをすれば指定ページにリダイレクトされました。

app > controllers > maps_controller.rb

class MapsController < ApplicationController
  before_action :authenticate_user!

    # 省略

  private
  def authenticate_user!
    redirect_to root_path
  end
end