#Sorceryとは?
Sorceryは、ユーザ認証機能を簡単に実装できるライブラリ
https://github.com/Sorcery/sorcery/wiki/Simple-Password-Authentication
#パスワード認証機能
今回は基本的な機能であるパスワード認証の実装
・ユーザー登録機能
・ログイン機能
・ログアウト機能
#Sorceryの導入
gem 'sorcery'
#Userモデルを作成
bundle exec rails g sorcery:installを実行し、Userモデルとデータベースのmigrationを生成します。
今回usersテーブルにはfull_nameカラムを追加そしてstring型と必須項目を追加。
#User登録機能を実装
Userモデルをベースに実装していきます。
モデルの実装
はじめに、Userモデルのフィールドである、
・email
・password
・password_confirmation
・full_name
に対するバリデーションを実装します。
class User < ActiveRecord::Base
authenticates_with_sorcery!
validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] }
validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] }
validates :email, uniqueness: true, precense: true
validates :full_name, presence: true
end
#コントローラーの実装
bundle exec rails g controller new createを実行
次にルーティングを定義しておきます。
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
resources :users, only: [:new, :create]
end
コントローラーの中身はこの様な感じです
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
redirect_to welcome_path #createアクションでUser登録が成功した際にリダイレクト先としてwelcome_pathを指定しています
else
render :new
end
end
private
def user_params #createで送られてきた値をparams.require
params.require(:user).permit(
:email,
:password,
:password_confirmation,
:full_name
)
end
end
welcome_pathはログイン画面へのパスのためこのままだとroutingエラーになるので後ほどログイン画面へのルーティングを記述します。
#Viewの実装
Form_withを使用します。
Bootstrapを使用。
<div class="container">
<div class="row">
<div class="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
<h1>ユーザー登録</h1>
<%= form_with model: @user, local: true do |f| %>
<div class= "form-group">
<%=f.label :full_name %>
<%= f.last_name :full_name, class: form-control %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<%= f.submit '登録', class: 'btn btn-primary' %>
<% end %>
<div class='text-center'>
<%= link_to 'ログインページへ', login_path %>
</div>
</div>
</div>
form_withでつまづく可能性があるので参考になるサイトを載せます。
#ログイン画面へのルーティング
ログイン画面はSessionControllerというコントローラーを作成しなければいけません?
$bundle exec rails g controller session new create destroy
get 'welcome', to: 'session#new'
post 'login', to: 'session#create'
logout 'logout', to: 'session#destory'
これでwelcome_pathへるぱが作成され、ログイン画面へのルーティングが可能となりユーザ登録機能が実装できました。
しかし、ここまでの実装ではsorceryの提供する機能は使っていません。
次からsorceryを使った認証機能を実装していきます。
#認証機能を実装
ここでは、次のようなシナリオを考えてみます。
認証が必要なページへアクセスした場合
・認証済みの場合
要求されたページを応答する。
・認証されていない場合
ログインページを応答する。
・認証が不要なページへアクセスした場合
要求されたページを応答する。
これを実装するにはルーティングに認証が必要となるページへルーティングを追加します。HomeControllerのindexアクションが該当するものとして、このコントローラをbundle exec rails g controller home indexを実行して作成します。また、home#indexをルートパスとして定義するため、config/routes.rbに以下を追加します
root to: 'home#index'
この時点では認証なしでどこのページでもアクセスできる状態です。
#認証済み判定処理
認証が必要なページがリクエストされた場合、認証済みか否かを判定する必要があります。 これを実現するには、Sorceryが提供するrequire_loginメソッドをbefore_actionに指定します。 これは、ApplicationControllerに書きます。 また、require_loginをbefore_actionに指定するにあたり、認証されていない場合の処理も合わせて実装する必要があります。 デフォルトでは、Sorceryは、not_authenticatedというメソッドを実行するため、この名前で実装します。ここでは、認証されていない場合は、ログインページへリダイレクトする実装としています。
before_action :require_login
protected
def not_authenticated
redirect_to welcome_path
end
ですがこのままではログインページ自体もbefore_actionが動作してしまうため認証済み判定が不必要なControllerではbefore_actionをスキップする必要があります。例えば以下のコードはSession_controllerの実装です
skip_before_action :reqire_login, except: [:destroy]