認証機能 authenticated

[5]認証機能
1.認証機能
アプリケーションを提供する立場にあるとき、無償の場合であってもユーザを限定して利用してもらうためには、何らかの仕組みが必要となります。それが認証機能です。今回はRuby on Rails上のアプリケーションに実装します。

1-1.プロジェクトの生成
(1) プロジェクトAppli004を生成する
(2) 日本語環境の設定
(3) データベースの作成

1-2.ログイン認証プラグインacts_as_authenticatedのインストール
(1) プラグインの導入


コマンド プロンプト
D:\Rails_Projects\Appli004>ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_authenticated
+ ./CHANGELOG
+ ./README
+ ./generators/authenticated/USAGE
+ ./generators/suthenticated/authenticated_generator.rb
+ ./generators/suthenticated/templates/authenticated_system.rb
+ ./generators/suthenticated/templates/authenticated_test_helper.rb
+ ./generators/suthenticated/templates/controller.rb
+ ./generators/suthenticated/templates/fixtures.yml
+ ./generators/suthenticated/templates/functional_test.rb
+ ./generators/suthenticated/templates/helper.rb
+ ./generators/suthenticated/templates/index.rhtml
+ ./generators/suthenticated/templates/login.rhtml
+ ./generators/suthenticated/templates/migration.rb
+ ./generators/suthenticated/templates/model.rb
+ ./generators/suthenticated/templates/signup.rhtml
+ ./generators/suthenticated/templates/unit_test.rb
+ ./generators/suthenticated_mailer/USAGE
+ ./generators/suthenticated_mailer/authenticated_mailer_generator.rb
+ ./generators/suthenticated_mailer/templates/activation.rhtml
+ ./generators/suthenticated_mailer/templates/notifier.rb
+ ./generators/suthenticated_mailer/templates/notifier_test.rb
+ ./generators/suthenticated_mailer/templates/observer.rb
+ ./generators/suthenticated_mailer/templates/signup_notification.rhtml
+ ./install.rb
acts_as_authenticated generator
====

DEPRECATED: Use restful_authentication instead. Or, ask me for commit rights if
you wish to maintain this plugin.

This is a basic authentication generator for rails, very much in the spirit of x
al's original Login Generator.

To use:

./script/generate authenticated user account

This generates a basic user model, a controller, some basic views, and tests. E
xtra functionality can be unlocked by
removing the comments for them. I have a few examples such as user activation a
nd reversible encrypted passwords.

This user migration is also generated unless you pass --skip-migration.

Generate your mailer:

./script/generate authenticated_mailer user

Consult the Acts As Authenticated wiki for more: http://technoweenie.stikipad.co
m/plugins/show/Acts+as+Authenticated

(2) authenticatedの生成


コマンド プロンプト
D:\Rails_Projects\Appli004>ruby script/generate authenticated user account
exists app/models/
exists app/controllers/
exists app/helpers/
exists app/views/account
exists test/functional/
exists test/unit/
create app/models/user.rb
create app/controllers/account_controller.rb
create lib/authenticated_system.rb
create lib/authenticated_test_helper.rb
create test/functional/account_controller_test.rb
create app/helpers/account_helper.rb
create test/unit/user_test.rb
create app/views/account/index.rhtml
create app/views/account/login.rhtml
create app/views/account/signup.rhtml
exists db/migrate
create db/migrate/20100204014203_create_users.rb

(3) NetBeansで[データベースマイグレーション]を選択し、[現在のバージョンへ]を実行します。


実行結果
(in D:/Rails_Projects/Appli004)
== CreateUsers: migrating ====================================================
-- create_table("users", {:force=>true})
-> 0.1410s
== CreateUsers: migrated (0.1410s) ===========================================

(4) 動作確認
WEBrickを立ち上げます。

(5) signupの実行
ブラウザからhttp://127.0.0.1:3000/account/signupを起動します。signup画面が表示されます。

(6) テストデータの投入
数件登録してみましょう。

LoginPassword
akagipwAkagi
itopwIto
uenopwUeno

登録に成功すると次の画面が表示されます。

(7) loginの実行
次にブラウザからhttp://127.0.0.1:3000/account/loginを起動します。login画面が表示されます。

login動作を確認します。併せてhttp://127.0.0.1:3000/accunt/logoutの動きも確認してください。

1-3.ログイン認証プラグインの改良
通常のアプリケーションでは、上記のloginとlogoutを使いますが運用上loginに不足している機能があります。
それはパスワード変更機能です。ここではログイン時にパスワード変更機能を持たせるための改良を行います。
(1) ビューの修正


/app/views/account/login.html.erb
<% form_tag do -%>
<p><label for="login">Login</label><br/><%= text_field_tag 'login' %></p>

<p><label for="password">Password</label><br/><%= password_field_tag 'password' %></p>

<p><label for="new_password">New Password</label><br/><%= password_field_tag 'new_password' %></p>

<p><label for="new_password_confirmation">New Confirm Password</label><br/><%= password_field_tag 'new_password_confirmation' %></p>
<!-- Uncomment this if you want this functionality
<p><label for="remember_me">Remember me:</label><%= check_box_tag 'remember_me' %></p>
-->

<p><%= submit_tag 'Log in' %></p><% end -%>

(2) コントローラの修正


/app/controllers/account_controller.eb
class AccountController < ApplicationController

:
:
:
def login
return unless request.post?
return unless (params[:new_password] == params[:new_password_confirmation])
self.current_user = User.authenticate(params[:login], params[:password])
if logged_in?
if params[:remember_me] == "1"
self.current_user.remember_me
cookies[:auth_token] = { :value => self.current_user.remember_token ,
:expires => self.current_user.remember_token_expires_at }
end
flash[:notice] = "Logged in successfully"
if params[:new_password]
@user = User.find(self.current_user.id)
@user.password = params[:new_password]
@user.password_confirmation = params[:new_password_confirmation]
@user.save!
flash[:notice] = "Password changed"
end

redirect_back_or_default(:controller => '/board', :action => 'index')
end
rescue ActiveRecord::RecordInvalid
render :action => 'login'
end
:
:
:
end

(3) 動作確認
ブラウザからhttp://127.0.0.1:3000/account/loginを起動します。

1-4.アプリケーションの作成
(1) scaffoldの利用
NetBeansで[生成...]を選択
    ジェネレータ(G): scaffold
    モデル名(N): Address
    属性ペア(フィールド型)(A): namae:string yubin:string jusho:string denwa:string


実行結果
exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/addresses
exists app/views/layouts/
exists test/functional/
exists test/unit/
create test/unit/helpers/
exists public/stylesheets/
create app/views/addresses/index.html.erb
create app/views/addresses/show.html.erb
create app/views/addresses/new.html.erb
create app/views/addresses/edit.html.erb
create app/views/layouts/addresses.html.erb
create public/stylesheets/scaffold.css
create app/controllers/addresses_controller.rb
create test/functional/addresses_controller_test.rb
create app/helpers/addresses_helper.rb
create test/unit/helpers/addresses_helper_test.rb
route map.resources :addresses
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/address.rb
create test/unit/address_test.rb
create test/fixtures/addresses.yml
exists db/migrate
create db/migrate/20100204020739_create_addresses.rb

(2) マイグレーションファイルの実行
NetBeansで[データベースマイグレーション]→[現在のバージョンへ]を選択します。


実行結果
(in D:/Rails_Projects/Appli004)
== CreateAddresses: migrating ================================================
-- create_table(:addresses)
-> 0.0940s
== CreateAddresses: migrated (0.0940s) =======================================

(3) 生成されたプログラムの実行
http://127.0.0.1:3000/addresses/を実行します。

1-5.ログイン機能のアプリケーションへの組み込み
認証機能のaccountプログラムとアプリケーションであるaddressプログラムをそれぞれ独立して作成しましたが、ここでそのプログラムを合体します。ほとんどのアプリケーションはこの方法で十分です。
  ・addressesアプリケーションのすべてのメソッドを実行する前にLoginが済んでいるかチェックを入れる
  ・addressesアプリケーションの終了時にLogoutメソッドを呼び出す
  ・Loginメソッドの実行後、addressesアプリケーションのindexメソッド(最初のメソッド)を呼び出す
  ・Singupメソッドの終了後はLoginメソッドを呼び出す
  ・Logoutメソッドの終了後はLoginメソッドを呼び出す



(1) application_controller.rbの修正
account_controler.rbの上の方に書いてある以下のコーディングを入れます。


/app/controllers/application_controller.eb
# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.

class ApplicationController < ActionController::Base
# Be sure to include AuthenticationSystem in Application Controller instead
include AuthenticatedSystem
# If you want "remember me" functionality, add this before_filter to Application Controller
before_filter :login_from_cookie

before_filter :set_charset
private
def set_charset
headers['Content-Type']="text/html; charset=utf-8"
end
:
:
end



(2) account_controller.rbの修正
上の方に書いてある以下のコーディングを削ります。


/app/controlers/account_controller.rb
class AccountController < ApplicationController
# Be sure to include AuthenticationSystem in Application Controller instead
include AuthenticatedSystem
# If you want "remember me" functionality, add this before_filter to Application Controller
before_filter :login_from_cookie

# say something nice, you goof! something sweet.
def index
redirect_to(:action => 'signup') unless logged_in? || User.count > 0
end
:
:
end



(3) loginアクションの修正(戻り値の変更)


/app/controlers/account_controller.rb

def login
return unless request.post?
self.current_user = User.authenticate(params[:login], params[:password])
if logged_in?
if params[:remember_me] == "1"
self.current_user.remember_me
cookies[:auth_token] = { :value => self.current_user.remember_token ,
:expires => self.current_user.remember_token_expires_at }
end
redirect_back_or_default(:controller => '/addresses', :action => 'index')
flash[:notice] = "Logged in successfully"
end
end



(4) signupアクションの修正(戻り値の変更)


/app/controlers/account_controller.rb

def signup
@user = User.new(params[:user])
return unless request.post?
@user.save!
self.current_user = @user
redirect_back_or_default(:controller => '/account', :action => 'login')
flash[:notice] = "Thanks for signing up!"
rescue ActiveRecord::RecordInvalid
render :action => 'signup'
end



(5) logoutアクションの修正(戻り値の変更)


/app/controlers/account_controller.rb

def logout
self.current_user.forget_me if logged_in?
cookies.delete :auth_token
reset_session
flash[:notice] = "You have been logged out."
redirect_back_or_default(:controller => '/account', :action => 'login')
end



(6) login事前チェックの導入


/app/controlers/adresses_controller.rb
class AddressesController < ApplicationController
before_filter :login_required

# GET /addresses
# GET /addresses.xml
def index
@addresses = Address.find(:all)

respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @addresses }
end
end
:
:
end



(7) logoutへのリンク導入


/app/views/addresses/index.html.erb
<h1>Listing addresses</h1>

<table>
<tr>
<th>Namae</th>
<th>Yubin</th>
<th>Jusho</th>
<th>Denwa</th>
</tr><% for address in @addresses %>
<tr>
<td><%=h address.namae %></td>
<td><%=h address.yubin %></td>
<td><%=h address.jusho %></td>
<td><%=h address.denwa %></td>

<td><%= link_to 'Show', address %></td>
<td><%= link_to 'Edit', edit_address_path(address) %></td>
<td><%= link_to 'Destroy', address, :confirm => 'Are you sure?', :method => :delete %></td>
</tr><% end %>
</table>
<br /><%= link_to 'New address', new_address_path %>
<%= link_to 'Logout', {:controller => 'account', :action => 'logout'} %>



ActiveForm | index | Ajax