Recipe 14.4. Building Authentication with acts_as_authenticated


Problem

You want to have portions of your application restricted to authorized users. You've looked into complete authentication systems, such as the Salted Login Generator, but have found that it won't meet your needs. You just want a foundation for an authentication system that allows you to develop the specifics of how it ties into your application.

Solution

Use the acts_as_authenticated plug-in and then build on the model and methods it provides to complete your authentication system. Start by installing the plug-in into your application.

$ ruby script/plugin source http://svn.techno-weenie.net/projects/plugins $ ruby script/plugin install acts_as_authenticated             

Your application has a reporting section to which you want to restrict access. The reports table is set up with the following schema:

db/schema.rb:

ActiveRecord::Schema.define() do   create_table "reports", :force => true do |t|     t.column "title", :string     t.column "summary", :text     t.column "details", :text   end end

To initialize a basic authentication system, run the authenticated generator provided by the plug-in, passing it a model name and a controller name. The following command sets up a User model and an Account controller, and creates a database migration:

$ ruby script/generate authenticated user account       exists  app/models/       exists  app/controllers/       exists  app/helpers/       create  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  test/fixtures/users.yml       create  app/views/account/index.rhtml       create  app/views/account/login.rhtml       create  app/views/account/signup.rhtml       exists  db/migrate       create  db/migrate/002_create_users.rb

Apply the migration to your database with rake:

$ rake db:migrate             

At the top of the account_controller.rb file, you'll see a line with include AuthenticationSystem. Move this line to your Application controller:

app/controllers/application.rb:

class ApplicationController < ActionController::Base   include AuthenticatedSystem end

To apply basic authentication to the actions of a controller, add a before filter on the controller class definition, passing it :login_required:

app/controllers/report_controller.rb:

class ReportController < ApplicationController   before_filter :login_required   def index   end  end

You can modify your layout to provide users the option to log out. The logout link is visible only to logged in users. This file is also a good place to display flash notices generated by the authentication actions.

app/views/layouts/application.rhtml:

<html>   <head>       <title>Rails Demo</title>   </head>    <body>       <% if logged_in? %>       <%= link_to 'logout', :controller => 'account', :action => 'logout' %>     <% end %>     <p style="color: green;"><%= flash[:notice] %></p>     <%= @content_for_layout %>   </body>  </html>

To add descriptive messages to failure events, such as invalid login attempts or sign-up validation errors, add the following flash assignments to the Account Controller.

app/controllers/account_controller.rb:

class AccountController < ApplicationController   def index     redirect_to(:action => 'signup') unless logged_in? or User.count > 0   end   def login     return unless request.post?     self.current_user = User.authenticate(params[:login], params[:password])     if current_user       redirect_back_or_default(:controller => '/report', :action => 'index')       flash[:notice] = "Logged in successfully"     else       flash[:notice] = "Invalid Login/Password!"     end   end   def signup     @user = User.new(params[:user])     return unless request.post?     if @user.save       redirect_back_or_default(:controller => '/report', :action => 'index')       flash[:notice] = "Thanks for signing up!"     else       flash[:notice] = @user.errors.full_messages.join("<br />")     end   end   def logout     self.current_user = nil     flash[:notice] = "You have been logged out."     redirect_back_or_default(:controller => '/account', :action => 'login')   end end

Discussion

When you restart your application, attempts to view the reports page will be redirected to the default login form created by the authenticated generator. The generator also creates a basic sign-up form that the login page links to. The following method keeps track of the initial URL; it is used for redirection once users authenticate.

def (default)   session[:return_to] ? redirect_to_url(session[:return_to]) \                       : redirect_to(default)   session[:return_to] = nil end 

Figure 14-2 shows the default sign-up and login form provided by the plug-in.

Figure 14-2. An authentication system with options to sign up, log in, and log out


The implementation details provided by acts_as_authenticated are deliberately minimalistic, for the same reasons that Rails does not provide an authentication system: there are many different ways to do authentication, and the authentication method you choose has serious implications on the design of the rest of your application. Authentication is not an area in which being prescriptive is very helpful.

See Also

  • The acts_as_authenticated plug-in home page: http://technoweenie.stikipad.com/plugins/show/Acts+as+Authenticated




Rails Cookbook
Rails Cookbook (Cookbooks (OReilly))
ISBN: 0596527314
EAN: 2147483647
Year: 2007
Pages: 250
Authors: Rob Orsini

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net