restful_authenticationを利用してみる(An introduction log of restful_authentication)

以前は専らlogin_engine、user_engineのお世話になっていたのだが、Rails2.0以降は手軽に利用できる環境ではなくなってしまった...。ということで、restful_authenticationを利用したログイン管理を試してみることに。

todoプロジェクトの作成(The making of the ToDo project)

  • いつもの手順で実験用にtodoプロジェクトをサクッと作る。
    • I made a ToDo project for experiments quickly.
$ rails todo
$ cd todo
$ script/generate scaffold todo body:string due:date done:boolean
$ rake db:migrate
$ script/server
  • これだけでちゃんと動いてしまうんだから、便利になったものだ。
    • It became convenient, because it will work perfectly by the above.


restful_authenticationのインストールと設定(Installation and setting of restful_authentication)

script/plugin install
$ script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/
script/generate authenticated
  • インストールが完了すると、READMEの内容が表示された。
    • When installation was completed, contents of README were displayed.
  • READMEによると、まずはscript/generate authenticated user sessionsを実行する必要があるようだ*1
    • According to README, first it seems that has the necessity to execute "script/generate authenticated user sessions"
  • オプションが設定できるようになっている。
    • The option can be set.
--include-activation メールによる認証を行う(Activation by e-mail is used.)
--stateful acts_as_state_machineと連携した処理を行う(Support for acts_as_state_machine, and the activation.)
--skip-migration userのマイグレーションファイルを生成しない(Skip the user migration.)
  • このtodoプロジェクトでは、acts_as_state_machineは利用しないが、メール認証は行う設定にした。
    • In this ToDo project, acts_as_state_machine did not use, but activation by e-mail is used.
$ script/generate authenticated user sessions --include-activation
rake db:migrate
  • 上記ジェネレーターによって、usersテーブル用のマイグレーションファイルが設定されているので実行した。
    • By the above generator, the migration file for users table was set up, and I executed command following.
$ rake db:migrate
include AuthenticatedSystem
  • sessions_controller.rbやusers_controller.rbを見ると、以下のようにコメントされている。
    • It was commented as follows when I read sessions_controller.rb and users_controller.rb.
# ---------- app/controllers/sessions_controller.rb ----------
class SessionsController < ApplicationController
  # Be sure to include AuthenticationSystem in Application Controller instead
  include AuthenticatedSystem
...(中略)...
  • コメントに従って、コントローラーのapplication.rbへコピーした。(これで、lib/authenticated_system.rbのメソッド定義は、すべてのコントローラーで利用できるようになる。)
    • According to comment, I copied it to controller's application.rb. Now I can use a method of lib/authenticated_system.rb with all controllers.
# ---------- app/controllers/application.rb ----------
class ApplicationController < ActionController::Base
  include AuthenticatedSystem

  helper :all # include all helpers, all the time
...(中略)...
before_filter :login_required
  • ログイン認証を必要とする場合は、そのコントローラーにbefore_filter :login_requiredを追記する。
    • When the login authentication is necessary, I add "before_filter_:login_required" to the controller.
  • これで、そのコントローラーのアクションを実行するには、すべてのアクションでログインが必要になった。
    • Now, login is needed with all the actions of the controller.
# ---------- app/controllers/todos_controller.rb ----------
class TodosController < ApplicationController
  before_filter :login_required
...(中略)...
  • ちなみに、アクションを限定したフィルターというのも可能だ。
    • By the way, the filter which limited action is possible.
# new, create, edit, update, destroyアクションのみ、ログインが必要
before_filter :login_required , :only => [:new, :create, :edit, :update, :destroy]

# index, showアクション以外は、ログインが必要
before_filter :login_required , :except => [:index, :show]

動作確認(Operation check)

以上で、まだメールの送信はできないが、それ以外の部分で提供される動作を確認してみた。restful_authenticationは、現状で以下の基本的な動作を提供してくれる。
It cannot send mail yet, I have tested other functions. Now restful_authentication adds the following basic functions.

動作(Event) URL HTTPメソッド(method) ルートパス名(Named route path) 処理されるコントローラー, アクション(controller, action)
ログインのページ(Show login page) http://localhost:3000/session/new GET new_session_path sessions_controller, new
ログインの実行(Login) http://localhost:3000/session POST session_path sessions_controller, create
ログアウトの実行(Logout) http://localhost:3000/session DELETE session_path sessions_controller, destroy
ユーザー登録のページ(Show sign up page) http://localhost:3000/users/new GET new_user_path users_controller, new
ユーザー登録の実行(Sign up) http://localhost:3000/users POST user_path(User.new) users_controller, create
  • まずは今まで通りhttp://localhost:3000/todosにアクセスしてみると...(サーバーの再起動が必要。control-Cで一旦中止してscript/server。)

  • ログイン認証を求められた!うまく動いている感じ。
    • Login was required! It is working well.

  • ユーザー登録ページが表示された。順調。
    • A signup page was displayed. Good.
  • メール認証は未設定だが、とりあえず登録してみると...
    • I don't yet do the setting of Activation, but I try to sign up...

  • あっ、開発用のプロジェクトのルートページが表示されてしまった...。
    • Oops, the route page of a project for development has been displayed.
  • でも、ユーザー登録直後はログイン状態のようで、http://localhost:3000/todosにアクセスしてみると、ちゃんと表示された。

  • あっ、ログアウトにはDELETEメソッドのリンクが必要だ...。このままだとログアウトできない。
    • Oops, the link of the DELETE method is necessary to logout. Now, I cannot log out.
  • ちなみに、ログアウトできたとしても、現状ではメール認証前なので、再ログインできない。
    • By the way, I cannot log in again even if able to log out because I am before Activation under the present conditions.
  • メール認証が完了した時点で、再ログインが可能になる。
    • When Activation was completed, login is enabled.

必要な修正(Necessary revisions)

プロジェクトのルートページが必要(The route page of a tidy project is required.)
  • config/routes.rbの下の方にコメントアウトされている「map.root :controller => "welcome"」を有効にした。
    • I deleted the comment mark of "# map.root :controller =>'welcome'" in bottom of "config/routes.rb". Then the route became effectively.
# ---------- config/routes.rb ----------
ActionController::Routing::Routes.draw do |map|
  map.resources :users

  map.resource :session

  map.resources :todos
...(中略)...
  # You can have the root of your site routed with map.root -- just remember to delete public/index.html.
  map.root :controller => "welcome"

  # See how all your routes lay out with "rake routes"

  # Install the default routes as the lowest priority.
  map.connect ':controller/:action/:id'
  map.connect ':controller/:action/:id.:format'
end
  • welcomeコントローラーの作成
    • The making of the welcome_controller
$ script/generate controller welcome
  • welcomeコントローラーにも、before_filter :login_requiredを追記した。
    • I added "before_filter :login_required" to the welcome_controller also.
  • コントローラーにアクションの設定は無いが、ビューがあれば処理される。
    • Welcome_controller does not have the setting of the Action, but it is handled if there is the View.
# ---------- app/controllers/welcome_controller.rb ----------
class WelcomeController < ApplicationController
  before_filter :login_required
end
  • app/views/welcome/index.html.erbを追加して、とりあえず以下のように編集した。
    • I added a file "App/views/welcome/index.html.erb", then I edited it as follows.
<%# ---------- app/views/welcome/index.html.erb ---------- %>
<p><%= current_user.login %> さん、Todoへようこそ!</p>

<%= link_to 'Todoリストへ', todos_path %>
  • さらに、http://localhost:3000/でwelcomeページにアクセスするためには、public/index.htmlを削除する必要がある。
  • とりあえず、ファイル名を「index.html~」に変更することで、welcomeページは表示されるようになった。
    • The welcome page was displayed by changing a file name into "index.html~."


ログイン、ログアウト、ユーザー登録のためのリンクが必要(The link for login, logout, and signup is required.)

URLを直接入力では面倒だし、ログアウトもできない。ページ間を移動できるようにリンクを設定してみた。
It is troublesome to input URL directly, and the logout is not possible, too. The link was set up in order to move between pages.

  • ログインページから、ユーザー登録ページへのリンク
    • The link from login page to signup page
<%# ---------- app/views/sessions/new.html.erb ---------- %>
...(中略)...
<p><%= link_to 'Signup >>', new_user_path %></p>
  • ユーザー登録ページから、ログインページへのリンク
    • The link from signup page to login page
<%# ---------- app/views/users/new.html.erb ---------- %>
...(中略)...
<p><%= link_to '<< Cancel', new_session_path %></p>
  • ログアウトのリンクをレイアウトファイルに設定した。これで、いつでもログアウトできる。
    • I set a link of the logout in a layout file. Now, it can log out at any time.
  • ファイル名をtodos.html.erbからapplication.html.erbに変更して、すべてのコントローラーに共通のレイアウトにした。
    • I changed the file name in application.html.erb from todos.html.erb and made it the layout that was common to all controllers.
<%# ---------- app/views/layouts/application.html.erb ---------- %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title><%= controller.controller_name %>: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'scaffold' %>
</head>
<body>

<%# ---------- ログアウトのリンクを追記(add logout link) ---------- %>
<p align="right">
<%= link_to_if logged_in?, 'Logout >>', session_path, :method => :delete do
    end %>
</p>

<p style="color: green"><%= flash[:notice] %></p>

<%= yield  %>

</body>
</html>


以上の修正で、ページ間を気持ち良くに移動できるようになった。
In the above-mentioned revision, I got possible to move from a page to a page comfortably.

メール認証の設定(Setting of activation by e-mail)

config/environment.rbの設定(Setting of "config/environment.rb")
  • Userモデルを監視するuser_observerを有効にする。
    • I validated user_observer watching the User model.
# ---------- config/environment.rb ----------
...(中略)...
Rails::Initializer.run do |config|
...(中略)...
  config.active_record.observers = :user_observer
end
config/routes.rbの設定(Setting of "config/routes.rb")
# ---------- config/routes.rb ----------
ActionController::Routing::Routes.draw do |map|
  map.resources :users

  map.resource :session

  map.resources :todos

  map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate'
...(中略)...
  # You can have the root of your site routed with map.root -- just remember to delete public/index.html.
  map.root :controller => "welcome"

  # See how all your routes lay out with "rake routes"

  # Install the default routes as the lowest priority.
  map.connect ':controller/:action/:id'
  map.connect ':controller/:action/:id.:format'
end
config/initializers/mail.rbの設定(Setting of "config/initializers/mail.rb")
  • mail.rbファイルを新規作成して、メールを送信するための設定を追記した。
    • I made a mail.rb file newly and added setting to transmit an email.
  • .macでメールアドレスが「my_account@mac.com」の場合
    • When the email address is "my_account@mac.com" of .mac.
# ---------- config/initializers/mail.rb ----------
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
  :address => "smtp.mac.com",
  :port => 587,
  :domain => "www.example-domain.com",
  :authentication => :login,
  :user_name => "my_account",
  :password => "パスワード"
}
app/models/user_mailer.rbの設定(Setting of "app/models/user_mailer.rb")
# ---------- app/models/user_mailer.rb ----------
class UserMailer < ActionMailer::Base
  def signup_notification(user)
    setup_email(user)
    @subject    += 'Please activate your new account'
    @body[:url]  = "http://localhost:3000/activate/#{user.activation_code}"
  end
  
  def activation(user)
    setup_email(user)
    @subject    += 'Your account has been activated!'
    @body[:url]  = "http://localhost:3000/"
  end
  
  protected
    def setup_email(user)
      @recipients  = "#{user.email}"
      @from        = "my_account@mac.com"
      @subject     = "[YOURSITE] "
      @sent_on     = Time.now
      @body[:user] = user
    end
end

メール認証の動作確認(Operation check of Activation)

  • 以上で一旦Todoサーバーを終了して、データベースも初期化した。(保存データをすべて破棄)(Now, I finished a Todo server and initialized the database. All the saved data is deleted.)
$ rake db:migrate:reset



  • Sign up」ボタンを押して暫くすると、アクティベーションを促すメールが届いた!
    • I pushed the "Sign up" button, and the email which promoted activation arrived in a few minutes!
	差出人: 	my_account@mac.com
	件名: 	[YOURSITE] Please activate your new account
	日時: 	2008年7月27日 15:11:53:JST
	宛先: 	test_account@mail.com

Your account has been created.

 Username: zarigani
 Password: 1234

Visit this url to activate your account:

 http://localhost:3000/activate/d32f034ce9687dfff2e14748f54556ea0f43f8c1
  • 上記メール記載のアドレスをクリックすると、「Signup complete!」が表示されて、無事アクティベーションが完了した。
    • "Signup complete!" was displayed when I clicked the address of above email mention, and activation was completed safely.


  • アクティベーションが完了したお知らせメールも届いた。
    • The information mail which activation completed also arrived.
	差出人: 	my_account@mac.com
	件名: 	[YOURSITE] Your account has been activated!
	日時: 	2008年7月27日 15:20:30:JST
	宛先: 	test_account@mail.com

zarigani, your account has been activated.  You may now start adding your plugins:

 http://localhost:3000/
  • その後一旦ログアウトして、再びログインしてみると、無事認証されTodoページに移動できた!
    • When I log out once and log in again afterwards, Login was completed safely and was able to move to the Todo page!


ひとまず、基本的な認証動作(ユーザー登録、メール認証、ログイン、ログアウトまで)が、出来るようになった!
The basic authentication --Signup, Activate, Login, Logout-- came to be possible!

参考ページ(Reference page)

以下のページがたいへん参考になりました。感謝です!
The following pages served as a reference very much.Thank you very much.

*1:引数「user」と「sessions」についても任意の名称を設定可能なようだ。