Building Authentication with acts_as_authenticatedProblemYou 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. SolutionUse 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 ><%= 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 DiscussionWhen 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 outThe 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
|