devise のインストール
develop から configure_devise というブランチを切って作業する。以下、このブランチでの作業。まず、Gemfile を設定した。
# a flexible authentication solution for Rails based on Warden gem 'devise', '~> 3.4.1'
bundle install する。
$ bundle install
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Installing bcrypt 3.1.9
Installing orm_adapter 0.5.0
Installing responders 2.0.2
Installing warden 1.2.3
Installing devise 3.4.1
Your bundle is complete!
It was installed into ./vendor/bundle
devise の設定
Generator を使って devise を設定する。
> bin/rails g devise:install create config/initializers/devise.rb create config/locales/devise.en.yml =============================================================================== Some setup you must do manually if you haven't yet: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> 4. If you are deploying on Heroku with Rails 3.2 only, you may want to set: config.assets.initialize_on_precompile = false On config/application.rb forcing your application to not access the DB or load models when precompiling your assets. 5. You can copy Devise views (for customization) to your app by running: rails g devise:views ===============================================================================
ここに書かれている手順通りに作業を進める。ここで、2 はすでにこれまでで実装済なのでスキップ。また、4 は Rails 3.2 の話なのでスキップ。
1 は default_url_options を設定することということで、development 環境であれば、config/environments/development.rb に
# environment for devise config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
と設定するとのこと。production 環境については、実際の運用環境の URL を設定する。本システムは学生用と教職員用が別れているが、ソースは共通なので、判別用のファイルを見て切り替える必要がある。まだこの部分は実装していないので、ToDo としてコメントを残しておく。
3 は app/views/layouts/application.html.haml に notice と alert の表記を入れる。今回は、yield の前にこんなふうに入れてみた。
%body -if notice .alert.alert-dismissable.alert-success %button.close{type:'button', 'data-dismiss' => 'alert'} × %p= notice -if alert .alert.alert-dismissable.alert-warning %button.close{type:'button', 'data-dismiss' => 'alert'} × %p= alert = yield
5 は view を独自に持つ場合の設定。前回は作成したが、現状ではペンディングにしてみる。
devise モデルの作成
前回のシステムと同じで User モデルを作成する。ここでできるモデルと 4 年前に作成したモデルの属性が一致すれば、現在使っているデータがそのまま流用できることになる。ということで、さっそく作成。
$ bin/rails g devise User invoke active_record create db/migrate/20141225022729_devise_create_users.rb create app/models/user.rb invoke rspec create spec/models/user_spec.rb invoke factory_girl create spec/factories/users.rb insert app/models/user.rb route devise_for :users
今回作成された db/migrate/*_devise_create_users.rb はこんな形。
class DeviseCreateUsers < ActiveRecord::Migration def change create_table(:users) do |t| ## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" ## Recoverable t.string :reset_password_token t.datetime :reset_password_sent_at ## Rememberable t.datetime :remember_created_at ## Trackable t.integer :sign_in_count, default: 0, null: false t.datetime :current_sign_in_at t.datetime :last_sign_in_at t.inet :current_sign_in_ip t.inet :last_sign_in_ip ## Confirmable # t.string :confirmation_token # t.datetime :confirmed_at # t.datetime :confirmation_sent_at # t.string :unconfirmed_email # Only if using reconfirmable ## Lockable # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts # t.string :unlock_token # Only if unlock strategy is :email or :both # t.datetime :locked_at t.timestamps end add_index :users, :email, unique: true add_index :users, :reset_password_token, unique: true # add_index :users, :confirmation_token, unique: true # add_index :users, :unlock_token, unique: true end end
旧システムは devise 1.1.2 の頃に作ったものであった。今回導入したものが 3.4.1 ということで、メジャーアップデートがすでに 2 回起こっている。旧システムは、当初ローカル認証だったものを LDAP 認証に変更したため、一部の属性は使わずに残っているものが多い。今回もデータベースの共有を目指しているので、属性を同一に設定したい。そこを踏まえて導入にあたる。旧のテーブルと新のテーブルを比較したところ、以下の属性は同じであった。
encrypted_password, reset_password_token, remember_created_at, sign_in_count, current_sign_in_at, last_sign_in_at, current_sign_in_ip, last_sign_in_ip
1.1.2 側にあって、3.4.1 側になくなった属性はこちら。
password_salt, remember_token, name, 他のモデルの関連ID
これらについて、調べてみた。password_salt については、1.2 の時に deprecated になっているとのこと。もともと、LDAP 認証にしているので、この部分は影響がないはずなので、テーブルに属性だけを挿入してしまう。
remember_token については、こちらで確認した。
Devise3.2.2 のデフォルト設定では、Rememberable の remember_token のカラムがないのでソースを解読してみた。remember_token フィールドを作成しない場合には、encrypted_password フィールドの値が使われるとのこと。今回は、LDAP 認証であるため、encrypted_password フィールドは使わない。こちらも、テーブルに属性を追加してみる。
name はシステムで設定した認証キーである。これも追加する。他のモデルについては後で設定するが、データの同期を確かめたいので属性だけ先に追加しておく。
一方、3.4.1 側にあって、1.1.2 側にない属性はこちら。
reset_password_sent_at
これは、Recoverable を設定したときに必要だが、LDAP 認証のため使わない。devise の設定で Recoverable を設定しなければ必要ないので、今回は登録しない。
最終的にはこんな感じになった。
class DeviseCreateUsers < ActiveRecord::Migration def change create_table(:users) do |t| ## Database authenticatable t.string :name, null: false, default: "" t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" t.string :password_salt # unused field ## Recoverable t.string :reset_password_token # unused field # t.datetime :reset_password_sent_at # remove field for compatible ## Rememberable t.string :remember_token # unused field t.datetime :remember_created_at ## Trackable t.integer :sign_in_count, default: 0, null: false t.datetime :current_sign_in_at t.datetime :last_sign_in_at t.inet :current_sign_in_ip t.inet :last_sign_in_ip ## Confirmable # t.string :confirmation_token # t.datetime :confirmed_at # t.datetime :confirmation_sent_at # t.string :unconfirmed_email # Only if using reconfirmable ## Lockable # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts # t.string :unlock_token # Only if unlock strategy is :email or :both # t.datetime :locked_at # link to other models t.integer :kyouin_id t.integer :shokuin_id t.integer :gakusei_id t.timestamps end add_index :users, :name, unique: true add_index :users, :kyouin_id, unique: true add_index :users, :shokuin_id, unique: true add_index :users, :gakusei_id, unique: true # add_index :users, :reset_password_token, unique: true # add_index :users, :confirmation_token, unique: true # add_index :users, :unlock_token, unique: true end end
migrate してテーブルを作成する。
$ bin/rake db:migrate == 20141225022729 DeviseCreateUsers: migrating ================================ -- create_table(:users) -> 0.0451s -- add_index(:users, :name, {:unique=>true}) -> 0.0028s -- add_index(:users, :kyouin_id, {:unique=>true}) -> 0.0020s -- add_index(:users, :shokuin_id, {:unique=>true}) -> 0.0021s -- add_index(:users, :gakusei_id, {:unique=>true}) -> 0.0018s == 20141225022729 DeviseCreateUsers: migrated (0.0540s) =======================
Devise の LDAP 連携
次に devise の LDAP 連携を設定する。前回のシステムでは、devise_ldap_authenticatable の 0.4.6 であった。現在の最新は、0.8.1 である。まず、Gemfile を設定した。
# a LDAP based authentication strategy for the Devise authentication framework gem 'devise_ldap_authenticatable', '~> 0.8.1'
続いて、bundle install する。
$ bundle install
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Installing net-ldap 0.5.1
Installing devise_ldap_authenticatable 0.8.1
Your bundle is complete!
It was installed into ./vendor/bundle
次にシステムに devise_ldap_authenticatable をインストールする。
$ bin/rails g devise_ldap_authenticatable:install create config/ldap.yml insert config/initializers/devise.rb gsub app/models/user.rb insert app/controllers/application_controller.rb
システムがいろいろとファイルを修正したようなので、作業ツリーの差分を見ながら確認してみる(上記で自分が設定した部分は除く)。
- app/controllers/applicatoin_controller.rb
- LdapException が起こったときの例外処理が追加された
- app/models/user.rb
- LDAP だとほとんど設定が必要なくなる。最終的に以下のようになった
# @!attribute encrypted_password # @return [String] 暗号化されたパスワード(LDAP のため未使用。互換性のために維持) # @!attribute password_salt # @return [String] パスワードの付加文字列 (devise 1.2 からは削除。互換性のために維持) # @!attribute reset_password_token # @return [String] パスワードリセットのためのトークン(LDAP のため未使用。互換性のために維持) # @!attribute remember_token # @return [String] パスワード記憶のためのトークン(デフォルトで削除されているが、互換性のために維持) # @!attribute remember_created_at # @return [DateTime] パスワード記憶の日付 # @!attribute sign_in_count # @return [FixNum] サインイン数 # @!attribute current_sign_in_at # @return [DateTime] 現在のサインイン日付 # @!attribute last_sign_in_at # @return [DateTime] 最後にサインインした日付 # @!attribute current_sign_in_ip # @return [IPAddr] 現在のサインインIP # @!attribute last_sign_in_ip # @return [IPAddr] 最後にサインインしたIP # @!attribute kyouin_id # @return [FixNum] 教員ID # @!attribute gakusei_id # @return [FixNum] 学生ID # @!attribute shokuin_id # @return [FixNum] 職員ID # @!attribute name # @return [String] ログイン名 # @!attribute email' # @return [String] 電子メールアドレス class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable, :registerable, :recoverable, :validatable devise :ldap_authenticatable, :rememberable, :trackable end
- config/ldap.yml
- テストサーバが設定されたものが作成されているので、旧システムと同じく、学内の LDAP サーバを設定した
- config/routes.rb
- 「devise_for :users」の行が追加された
- config/initializers/devise.rb
- 旧システムの設定と見比べて以下の部分を修正
Devise.setup do |config| config.ldap_logger = true config.ldap_create_user = false config.authentication_keys = [ :name ] config.case_insensitive_keys = [ :name ] config.strip_whitespace_keys = [ :name ]
- config/locales/devise.en.yml
- 英語用の locale ファイルが追加された。せっかくなので、日本語用の locale ファイルを取得して設置した。
とりあえずここまでを configure_devise リポジトリにコミットした。
今日はここまで。
written by iHatenaSync