- お知らせ -
  • 当wikiのプログラムコードの表示を直してみました(ついでに長い行があると全体が下にぶっ飛ぶのも修正)。不具合があればBBSまでご連絡下さい。

Ruby/Ruby on Rails/Authlogic

はじめに Edit

Authlogicで、パスワードリマインダーを実装してみる。

Authlogicの公式にもチュートリアルがちゃんとありますが、
ここではforgot_passwordというプラグイン実装のパスワードリマインダージェネレーターを使ってさっくり導入できないかをもくろんでみます。

Rails 2.3.2で確認しました。

forgot_passwordの導入方法 Edit

主に↓を参考にしつつ導入してみます。
forgot_password with AuthLogic - Develop with pleasure!

ただし、上記ページ記述の "greenisus's forgot_password" ではなく、2009/08/05時点で比較的新しい "bhauman's forgot_password" の方を入れてみます。

以下のようにプラグインをインストールする

$ ruby script/plugin install git://github.com/bhauman/forgot_password.git
 :
 :
 * branch            HEAD       -> FETCH_HEAD
Thanks for using forgot_password!

In attempt to be flexible enough to work with multiple login systems (mainly res
tful-authentication and its ancestors), this plugin will generate a new controll
er to handle forgotten passwords.  Your user model must have accessors for passw
ord and password_confirmation, and handle its own password encryption.  I assume
 most people are using technoweenie's excellent restful-authentication plugin, s
o if you are you probably won't have any problems.

Usage:

ruby script/generate forgot_password <password-model-name> <user-model-name>

In most cases, that's probably:

ruby script/generate forgot_password password user

then run rake db:migrate and enjoy :)

次にジェネレータでモデルやコントローラー、ビューなどファイル一式を生成します。

ruby script/generate forgot_password <password-model-name> <user-model-name>

とあるので、generateの2番目の引数(<password-model-name>) にパスワード管理用モデル名、3番目の引数(<user-model-name>)にユーザー管理用モデル(Authlogicの場合はUserだろう)を指定して、生成させてみます。

$ ruby script/generate forgot_password forgot_password user

      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/forgot_passwords
      create  app/views/forgot_password_mailer
      create  app/models/forgot_password.rb
      create  app/models/forgot_password_mailer.rb
      create  app/controllers/forgot_passwords_controller.rb
      create  app/helpers/forgot_passwords_helper.rb
      create  app/views/forgot_passwords/new.html.erb
      create  app/views/forgot_passwords/reset.html.erb
      exists  db/migrate
      create  db/migrate/20090805082202_create_forgot_passwords.rb
      create  app/views/forgot_password_mailer/forgot_password.html.erb
      create  app/views/forgot_password_mailer/reset_password.html.erb
       route  map.resources :forgot_passwords
       route  map.change_password '/change_password/:reset_code', 
         :controller => 'forgot_passwords', :action => 'reset'
       route  map.forgot_password '/forgot_password', 
         :controller => 'forgot_passwords', :action => 'new'

※見やすいよう改行インデント入れてます

元の紹介ページにあった forgot_passwords_controller.rb の PasswordMailer.deliver_reset_password(@user) のコードの削除はこのバージョンのプラグインでは修正されているので修正必要はなし。

config/routes.rbに以下のルーティング設定が追加されていることを確認しつつ、

  map.forgot_password '/forgot_password', :controller => 'forgot_passwords', :action => 'new'
  map.change_password '/change_password/:reset_code', :controller => 'forgot_passwords', :action => 'reset'
  map.resources :forgot_passwords

おもむろに、マイグレーションを実行します。

$ rake db:migrate
(in c:/my_project/trunk)
==  CreateForgotPasswords: migrating =======================
-- create_table("forgot_passwords")
   -> 0.0940s
==  CreateForgotPasswords: migrated (0.0940s) ==============

※見やすいよう多少調整済み

あとは、ActionMailerの設定が終わっていないなら、その設定をする。

下記例では、自ホストに送信用のSMTPサーバーを立てている場合の例。
(SMTPサーバーは、Windows なら Radishを常駐させとくのが簡単かと)

  # setting for SMTP server
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => '127.0.0.1',
    :port => 25,
    :domain => "example.com"
  }
  # setting for japanese mail
  config.action_mailer.default_charset = 'iso-2022-jp'
  # raise exception on error
  config.action_mailer.raise_delivery_errors = true

このままでは日本語が化けますので、
ActionMailerJaプラグイン を導入してください。
導入方法については Ruby/Ruby on Rails/ActionMailerについて を参照下さい。

(…といいましても、

ruby script/plugin install git://github.com/kusakari/actionmailer_ja.git

して、サーバーを再起動するだけですが)

後は、ログイン画面の下辺りにでもリンクを配置しておくとよいです。

例:app\views\users_sessions\new.html.erb の一番下に下記を追加

<br/>
<%= link_to 'パスワードを忘れました', forgot_password_path %>

現在、動作を確認しながら様子見中…

以下、細かい不具合があるので、修正していきます。

不具合修正 Edit

以下を修正します。

  • パスワード再設定URLを送信後、トップではなく、ログイン画面に飛ばすように(まあこれは任意で)
  • パスワード再設定後ログインしたままになる問題を修正
    一旦、current_user_session.destroyでログアウトして、
    ログイン画面(new_user_session_path) に飛ばします。
  • deliver_forgot_password に request.raw_host_with_portを渡してリンクをパスワード再設定リンクをURLを動的に生成(この辺微妙に自信なし)

app/models/forgot_password_mailer.rb:

 class ForgotPasswordMailer < ActionMailer::Base
   
-  def forgot_password(password)
+  def forgot_password(password, host_with_port)
     setup_email(password.user)
     @subject    += 'You have requested to change your password'
-    @body[:url]  = "http://YOURSITE/change_password/#{password.reset_code}"
+    @body[:url]  = "http://#{host_with_port}/change_password/#{password.reset_code}"
   end

app/controllers/forgot_passwords_controller.rb:

     respond_to do |format|
       if @forgot_password.save
-        ForgotPasswordMailer.deliver_forgot_password(@forgot_password)
+        ForgotPasswordMailer.deliver_forgot_password(@forgot_password, request.raw_host_with_port)
         flash[:notice] = "A link to change your password has been sent to #{@forgot_password.email}."
-        format.html { redirect_to '/' }
+        format.html { redirect_to new_user_session_path }
         format.xml  { render :xml => @forgot_password, :status => :created, :location => @forgot_password }
       else
         # use a friendlier message than standard error on missing email address
         if @forgot_password.errors.on(:user)
     respond_to do |format|
       if @user.update_attributes(params[:user])
        @forgot_password.destroy
+       current_user_session.destroy
         ForgotPasswordMailer.deliver_reset_password(@user)
         flash[:notice] = "Password was successfully updated. Please log in."
-        format.html { redirect_to login_path}
+        format.html { redirect_to new_user_session_path }
       else
         format.html { render :action => :reset, :reset_code => params[:reset_code] }
       end
     end

国際化や日本語化は、生成されたファイル郡(上で記述)を見て一通り行ってみてください。

参考リンク Edit


No comment. Comments/Ruby/Ruby on Rails/Authlogic/パスワードリマインダーの実装?

Name:

Front page   Edit Freeze Diff Backup Upload Copy Rename Reload   New Pages Search Recent changes   Help   RSS of recent changes
Last-modified: 2009-12-14 Mon 11:04:53 JST (3647d)