sorceryを使用して、ユーザー登録・ログイン機能を作成
sorceryとは
Railsに認証機能を実装するためのライブラリ。
インストール
Gemfileに
gem 'sorcery'
と書きターミナルでbundle install
を実行。
初期設定
$ bundle exec rails g sorcery:install
これで必要最低限なファイルが作成される。
- config/initialize/sorcery.rb
- db/migrate/20xxxxxxxx_sorcery_core.rb
- app/models/users.rb
など
マイグレーションファイル(db/migrate/20xxxxxxxx_sorcery_core.rb)には、必要最低限のカラム(eメール、パスワード等)がすでに定義されている。ここに適宜必要なカラム(例えば氏名など)を追加しデータベースに反映させる。
bundle exec rails db:migrate
または
rake db:migrate
を実行する。
(ちなみに、bundle execはBundlerが管理するGemを利用できる状態でコマンドを実行するということ)
コントローラを設定
$ bundle exec rails g sorcery:install
を実行した事で、app/models/users.rbは作成されているが、usersコントローラは自分で作成する。
$ rails g controller users
を実行。
app/controllers/users_controller.rb
class UsersController < ApplicationController # ... private def user_params params.require(:user).permit(:email, :password, :password_confirmation) end end
また
$ rails g controller UserSessions new create destroy
でuser_sessions.controller.rbを作る。
app/controllers/user_sessions.controller.rb
class UserSessionsController < ApplicationController def create @user = login(params[:email], params[:password]) if @user redirect_back_or_to(:users, notice: 'Login successful') else flash.now[:alert] = 'Login failed' render :new end end def destroy logout redirect_to(:users, notice: 'Logged out!') end end
リダイレクト先やフラッシュなどは仕様に合わせて変更すれば良い。
usersコントローラでユーザー情報、user_sessionsコントローラでログイン/ログアウトに関する情報を扱う。
ルーティングを設定
config/routes.rb
root 'users#index' resources :users get 'login', to: 'user_sessions#new' post 'login', to: 'user_sessions#create' delete 'logout', to: 'user_sessions#destroy'
例えば、users_contoroller.rbでnewアクションとcreateアクションしか設定しないのであれば、
resources :users, only %i[new create]
という書き方もできる。
※リソースベースのルーティングを設定すると、URL用のヘルパーを使用することができるようになる。(login_pathのようなやつ)
モデル
app/models/users.rb
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 end
ログインフォーム
入力用のフォーム(パスワードがデータベースで暗号化される前にパスワードを保持しておくためのもの)
app/views/users/_form.html.erb
<div class="field"> <%= form.label :password %><br /> <%= form.password_field :password %> </div> <div class="field"> <%= form.label :password_confirmation %><br /> <%= form.password_field :password_confirmation %> </div>
ログイン用のフォーム
app/views/user_sessions/new.html.erb
<h1>Login</h1> <%= render 'form' %> <%= link_to 'Back', users_path %>
app/views/user_sessions/_form.html.erb
<%= form_with url: login_path, method: :post do |f| %> <div class="field"> <%= f.label :email %><br /> <%= f.text_field :email %> </div> <div class="field"> <%= f.label :password %><br /> <%= f.password_field :password %> </div> <div class="actions"> <%= f.submit "Login" %> </div> <% end %>
あとは、app/views/layouts/application.html.erbにナビゲーションリンクとフラッシュメッセージを表示するためのビューを用意する(もちろんフラッシュ用のパーシャルを作っても良い)。そこにログアウト用のリンクを作る。
注意:logoutのリンクでmethod: :deleteを指定し忘れないようにする。
そして、ユーザー登録用のビューをapp/views/users/new/html.erbとして作成する。
ログインしていないユーザーの権限を制限
sorceryには便利なメソッドが用意されている。
require_login(sorceryが用意しているので自分で定義しなくて良い)
ログインしていない状態だとログインページへリダイレクトさせる
# app/controllers/application_controller.rb # 全てのアクションが呼び出される前にrequire_loginメソッドを呼び出す before_action :require_login # app/controllers/users_controller.rb # users_controllerのindex,new,createアクションが呼び出されるときは、require_loginを呼び出さない skip_before_action :require_login, only: [:index, :new, :create] # app/controllers/user_sessions_controller.rb skip_before_action :require_login, only: [:new, :create]
参考サイト
Simple Password Authentication · Sorcery/sorcery Wiki · GitHub