Rails sorcery

やりたいこと

sorceryについて理解を深めたかったので、GitHubを参照し、Wiki等に記載されている内容をまとめます。 実装方法については深く解説していないで、詳しく知りたい方はsorceryのGitHubを参照してください


Userモデルを作成する

bundle exec rails g sorcery:install
class SorceryCore < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :email,            null: false
      t.string :crypted_password
      t.string :salt

      t.timestamps                null: false
    end

    add_index :users, :email, unique: true
  end
end
crypted_password

暗号化されたパスワード(crypted_password)。試しにrails consoleでユーザーを作成して、Userテーブルのcrypted_passwordを見てみるとめちゃ長い文字列になっている。

一方,users テーブルには password や password_confirmation というカラムは無い,ということも分かります。

password を暗号化した文字列を作成して crypted_passoword カラムに収めるのは sorcery が自動的にやってくれます。

パスワードが保存される過程は、 以下のように、「仮想的な」passwordフィールドを使用し、データベースに暗号化される前のパスワードをビューで扱う。 →このpassword属性はカラムに対応していないため、平文のパスワード情報がDBに保存されることは無い。 →パスワードは暗号化され、DBに保存される。


modelに記載されている内容

  authenticates_with_sorcery!

  validates :password, length: { minimum: 8 }, 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
  • validates :password, confirmation: trueはpasswordというDBに存在しない仮想的な属性(virtual attributes)が追加される。

  • if: -> { new_record? || changes[:crypted_password] }はユーザーがパスワード以外のプロフィール項目を更新したい場合に、パスワードの入力を省略できるようになる。


Controllerの内容

ログインページのcontorollerを参照しています。

user_sessions_controller.rb

class UserSessionsController < ApplicationController
  skip_before_action :require_login, only: %i[new create]
  def new; end

  def create
    @user = login(params[:email], params[:password])
    if @user
      redirect_back_or_to(root_path, notice: 'Login success')
    else
      render :new
    end
  end

  def destroy
    logout
    redirect_to(login_path, notice: 'ログアウトしました')
  end
end
redirect_back_or_to

githubで詳細を見てみると

      def redirect_back_or_to(url, flash_hash = {})
        redirect_to(session[:return_to_url] || url, flash: flash_hash)
        session[:return_to_url] = nil
      end

sessionのreturn to urlがなければこのurlになるみたいなメソッドが書かれている。

例えば、掲示板ページにアクセスしようとしたユーザにログインを要求する場合、require_loginメソッドでユーザをログインページに誘導し、ログインが成功したら、最初に訪れようとしていた掲示板ページにリダイレクトさせるということが可能になる。

参考

github.com