Railsでのはじめてのsorceryユーザー認証導入

今回は、Railsにユーザー認証を入れてみました。

ソース、動作については、以下で確認できます。

■github
https://github.com/dog-ears/demo_ror
■heroku
https://dog-ears-ror.herokuapp.com/
※以下アドレスからユーザー登録可能
https://dog-ears-ror.herokuapp.com/users/new

導入の流れは、こんな感じです。

(1)bcryptインストール
(2)sorceryのインストール
(3)UserSessionsの作成

では、やってみましょう。

まず、sorceryを使うには、gem ‘bcrypt’が必須のため、インストールします。

(1)bcryptインストール

■Railsでパスワードの取り扱い(bcrypt 3.1.7以上)
http://qiita.com/chobi9999/items/20b962a324a0bdbfc0dc

#Gemfile
# gem 'bcrypt', '~> 3.1.7'
↓
gem 'bcrypt', '~> 3.1.7'

ターミナルから、

bundle install

【★★★補足1★★★】 bundle installした後は、サーバーを再起動しましょう。

(2)sorceryのインストール

■[Ruby on Rails]sorceryによる認証-(1)メールアドレスとパスワードによる認証のチュートリアル
http://dev.classmethod.jp/server-side/ruby-on-rails/ruby-on-rails_sorcery_auth_no1/

なお、チュートリアルだと、カラムは以下の4つ(idとかは除く) ・email ・crypted_password ・salt ・timestamps なのですが、ここに名前(name)と権限(level)を追加。 さらに、bcrypt的には、カラム名は、 crypted_passwordではなく、password_digestがデフォらしいので、 そちらを採用します。

作るカラム ・name ・email ・password_digest ・level ・salt ・timestamps

#Gemfile
gem 'sorcery'

で、bundle install & サーバー再起動 次、sorceryの本体インストール

$ rails g sorcery:install

ここで、いくつかデフォルト設定をいじります。

▼パスワードの保存先カラム名の修正
#config/initializers/sorcery.rb

# change default crypted_password attribute.
# Default: `:crypted_password`
#
# user.crypted_password_attribute_name =

↓

# change default crypted_password attribute.
# Default: `:crypted_password`
#
user.crypted_password_attribute_name = :password_digest

▼マイグレーションファイルの修正

#db/migrate/[YYYYMMDDHHMMSS]_sorcery_core.rb

t.string :email,            :null => false
t.string :crypted_password
t.string :salt
↓
t.string :name,            :null => false
t.string :email,            :null => false
t.string :password_digest
t.integer :level
t.string :salt

スキャフォールドを使って、 モデルとマイグレーション以外(コントローラー・ビューなど)を作成

rails g scaffold user name:string email:string password_digest:string level:integer salt:string --migration false

モデルを上書きするか?と聞かれるが、すでに作成済みなので、No。
次に、test/fixtures/users.ymlを上書きするか?と聞かれますが、こちらは未作成なので、Yes。

rake db:migrate

▼モデルの修正
(i) bcryptの使用をモデル内で宣言

#/app/models/user.rb
authenticates_with_sorcery!
↓
authenticates_with_sorcery!
has_secure_password

これで「password」、「password_confirmation」のバリデーションなど、 いろいろ自動でやってくれます。

(ii)ActiveRecord enumsを設定
ユーザーの権限情報は、データベース上では数値で持たせるのですが、入力・出力時は、[管理者 / マネージャー / 一般]と表示したいので、 以下作業実行。

■Rails 4.2  ActiveRecord enumsを使って列挙型を扱ってみる
http://totech.hateblo.jp/entry/2015/12/19/144943

#/app/models/user.rb
enum level: { '管理者': 1, 'マネージャー': 2, '一般': 3 }

入力フォームは、あとでいじる必要あるけど、indexとshowに関しては、これでOK!

(iii)その他バリデーション追加

#/app/models/user.rb
validates :name, presence: true
validates :email, presence: true
validates :email, uniqueness: true

▼フォームから、「password」、「password_confirmation」を受け取れるようコントローラー修正

#/app/controllers/users_controller.rb
def user_params
  params.require(:user).permit(:name, :email, :password_digest, :level, :salt)
end
↓
def user_params
  params.require(:user).permit(:name, :email, :password, :password_confirmation, :level, :salt)
en

▼フォームの修正(ビューの修正)

#/app/views/users/_form.html.erb
<div class="field">
  <%= f.label :password_digest %><br>
  <%= f.text_field :password_digest %>
</div>
↓
<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>

<div class="field">
  <%= f.label :level %><br>
  <%= f.select :level, User.levels.keys %>
</div>

列挙型にしたlevelの書き方に注意。

#/app/views/users/index.html.erb #/app/views/users/show.html.erb
※github参照。

ここまでで、Userモデル作成完了。
次は、セッションを管理するUserSessionsを作ります。

(3)UserSessionsの作成 基本的に

■[Ruby on Rails]sorceryによる認証 – (1)メールアドレスとパスワードによる認証のチュートリアル
http://dev.classmethod.jp/server-side/ruby-on-rails/ruby-on-rails_sorcery_auth_no1/
の、 3.ログイン周りの作成 4.ログインしていないユーザの操作を制限する と同じですが、ルートの移動先は、トップページ(ダッシュボード)で、 ログインしてない場合は、ログインページに移動するようにします。

#/config/routes.rb
root :to => 'dashboard#index'
#/app/controllers/application_controller.rb
before_action:require_login
private

def not_authenticated
  redirect_to login_path, alert: "Please login first"
end
#/app/controllers/user_sessions_controller.rb
skip_before_action :require_login, except: [:destroy]

なお、フィルタ処理は、rails4.2では、 ***_filterより***_actionのほうがよいらしいので、そちらを採用しています。

■Rails4でアクションの前後にフィルタ/処理を挟み込む
http://ruby-rails.hatenadiary.com/entry/20141129/1417223453

最後に、テストを走らせたら、もろもろエラー・・・。 なんですが、実際の画面では動いてるので、テストは今回はしょります。 テスト関連は、今後の宿題。 以上、Railsでのはじめてのsorceryユーザー認証導入でした。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です