[Ruby on Rails]sorceryによる認証 – (2)ユーザ名による認証とRemember-Me
はじめに
前回に引き続きsorceryによる認証についてです。今回はユーザ名のよる認証と、Remember-Me機能の実装を行ってみました。
実装手順
前回と同様、基本的には公式サイトのチュートリアルに沿って実装しました。ですがチュートリアルではメールアドレスを使用しているので、これをユーザ名に変えることと、Remember-Me機能の追加を独自に行っています。以下、その手順です。メモを元に書いているので漏れ等あったら、すいませんw。
1.プロジェクトの作成〜sorceryのインストール
これらの手段は前回やチュートリアルと同様です。Gemfileへの記述と、コマンドだけ載せておきます。
Gemfile
gem 'sorcery'
$ bundle install --path vendor/bundle $ rails g sorcery:install
2.Remember-Meの追加
以下のコマンドを実行後、サブモジュールとして「remember-me」を取り込むよう定義ファイルに記述します。またタイムアウトの期間を設定します(ここでは2週間を秒単位で保持しています)。
$ rails g sorcery:install remember_me --migrations
config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [:remember_me] (中略) config.user_config do |user| (中略) user.remember_me_for = 1209600 # Two weeks in seconds (中略) end
3.ユーザ名を使用することの定義
sorceryはデフォルトではメールアドレスでユーザーを特定するようになっているため、ユーザ名を使用するよう定義ファイルを変更します。
config/initializers/sorcery.rb
user.username_attribute_names = [:username]
次にUserテーブルにも「email」ではなく「username」を保持するよう、migrationファイルを変更します。
db/migrate/作成日時_sorcery_core.rb
t.string :username, :null => false
4.Remember-MeをUserテーブルに追加
Userテーブルに「remember-me」を保持するよう、migrationファイルを追加します。
db/migrate/作成日時_add_rememver_me_users.rb
class AddRememverMeUsers < ActiveRecord::Migration def self.up add_column :users, :remember_me_token, :string, :default => nil add_column :users, :remember_me_token_expires_at, :datetime, :default => nil add_index :users, :remember_me_token end def self.down remove_index :users, :remember_me_token remove_column :users, :remember_me_token_expires_at remove_column :users, :remember_me_token end end
ここでmigrateを実行します。
$ rake db:migrate
5.Userのスキャフォールド
スキャフォールドを行いますが、ここも「email」ではなく「username」を使用するようにします。
$ rails g scaffold user username:string crypted_password:string salt:string --migration false
ユーザコントローラにて、ユーザ名やremember-meを受け取れるように以下のメソッドを追加します。
app/controllers/users_controller.rb
def user_params params.require(:user).permit(:username, :password, :password_confirmation, :remember_me) end
パスワードの入力欄を作成します。
app/views/users/_form.html.erb
<div class="field"> <%= f.label :password %><br /> <%= f.password_field :password %> </div> <div class="field"> <%= f.label :password_confirmation %><br /> <%= f.password_field :password_confirmation %> </div>
ユーザモデルを編集します。
app/models/user.rb
class User < ActiveRecord::Base authenticates_with_sorcery! validates :password, length: { minimum: 3 } validates :password, confirmation: true validates :password_confirmation, presence: true validates :username, uniqueness: true end [/ruby] </p> <h3>6.以降の手順</h3> <p> 以降の手順については、<a href="https://github.com/NoamB/sorcery/wiki/Simple-Password-Authentication" target="_blank" rel="noopener noreferrer">チュートリアル</a>にて「UserSessions」コントローラを作成するところ以降とほぼ同じです。チュートリアルの以下のコマンド以降になります。 今回変えたのは以下の箇所です。 </p> <p> <h5>app/controllers/user_sessions_controller.rb</h5> def create if @user = login(params[:username], params[:password], params[:remember]) redirect_back_or_to(:users, notice: 'Login successful') else flash.now[:alert] = 'Login failed' render action: 'new' end end def destroy remember_me! forget_me! logout redirect_to(:users, notice: 'Logged out!') end
「email」を「username」に変えています。また「destroy」アクションにてlogoutする前に「remember_me!」「forget_me!」を追加しています。これによりログアウト時にユーザのセッション情報を消すことが出来るようになります。
/app/views/user_sessions/_form.html.erb
<%= form_tag user_sessions_path, :method => :post do %> <div class="field"> <%= label_tag :username %><br /> <%= text_field_tag :username %> </div> <div class="field"> <%= label_tag :password %><br /> <%= password_field_tag :password %> </div> <div class="field"> <%= check_box_tag :remember_me, 1, params[:remember_me] %> <%= label_tag :remember_me %> </div> <div class="actions"> <%= submit_tag "Login" %> </div> <% end %>
こちらも「email」を「username」に変えています。また「remember_me」のチェックボックスを追加しています。
まとめ
sorceryの用意されている機能を元に、ユーザ名での認証・Remember-Meの実装を行うことができました。Remember-Meを実現するのに必要なサブモジュールを取り込みましたが、この必要に応じてモジュールを取り込むというのはsorceryの特徴の一つかと思います。