SunQuest
 
       Ruby-on-Rails
  Home arrow Ruby-on-Rails arrow Page 5 - Controlling Information Access with the Ra...
IBM developerWorks
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Dedicated Servers  
Actuate Whitepapers 
VeriSign Whitepapers 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
RUBY-ON-RAILS

Controlling Information Access with the Rails Action Controller
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 2
    2008-02-14

    Table of Contents:
  • Controlling Information Access with the Rails Action Controller
  • 4.13 Sending Files or Data Streams to the Browser
  • 4.14 Storing Session Information in a Database
  • 4.15 Tracking Information with Sessions
  • 4.16 Using Filters for Authentication

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT

    Stay one step ahead of the competition. Evaluate and give feedback on some of the hottest web development tools on the market today. Make your opinion heard! Click Here

    Controlling Information Access with the Rails Action Controller - 4.16 Using Filters for Authentication


    (Page 5 of 5 )

    Problem

    You want to authenticate users before they’re allowed to use certain areas of your application; you wish to redirect unauthenticated users to a login page. Furthermore, you want to remember the page that the user requested and, if authentication succeeds, redirect them to that page once they’ve authenticated. Finally, once a user has logged in, you want to remember his credentials and let him move around the site without having to re-authenticate.

    Solution

    Implement an authentication system, and apply it to selected controller actions using before_filter.

    First, create a user database to store user account information and login credentials. Always store passwords as hashed strings in your database, in case your server is compromised.

    db/migrate/001_create_users.rb: 

      class CreateUsers
    < ActiveRecord::Migration
        def self.up
         
    create_table :users do |t|
            t.column :first_name,        :string
            t.column :last_name,         :string
            t.column :username,          :string
           
    t.column :hashed_password,   :string
          end

          User.create :first_name => 'Rob',
                      :last_name => 'Orisni',
                      :username => 'rorsini',
                      :hashed_password =>
      '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'
        end

        def self.down
          drop_table :users
        end
      end

    In your ApplicationController, define an authenticate method that checks if a user is logged in and stores the URL of the page the user initially requested:

    app/controllers/application.rb:

      # Filters added to this controller will be
    run for all controllers in the
      # application. 
      # Likewise, all the methods added will be
    available for all controllers.
      class ApplicationController
    < ActionController::Base
        def authenticate
         
    if session['user'].nil?
            session['initial_uri'] = request.request_uri     
            redirect_to :controller => "users",
    :action => "login
         
    end
        end
     end

    To make sure the authenticate method is invoked, pass the symbol :authenticate to before_filter in each controller that gives access to pages requiring authentication. Here’s how to make sure that users are authenticated before they can access anything governed by the ArticlesController or the BooksController:

    app/controllers/articles_controller.rb:

      class ArticlesController
    < ApplicationController

        before_filter :authenticate

        def admin
        end
      end

    app/controllers/books_controller.rb:

      class BooksController
    < ApplicationController

        before_filter :authenticate

        def admin
        end
      end

    Now, create a login form template to collect user credentials:

    app/views/users/login.rhtml:

      <% if flash['notice'] %>
        <p style="color: red;"><%= flash['notice'] %></p>
      <% end %>

      <% form_tag :action => 'verify' do %>

        <p><label
    for="user_username">Username</label>;
        <%= text_field 'user', 'username' %> </p>  

        <p><label
    for="user_hashed_password">Password</label>;
        <%=  password_field 'user', 'hashed_password' %> </p> 

        <%= submit_tag "Login" %>
      <% end %>

    The UsersController defines login, verify, and logout methods to handle the authentication of new users:

    app/controllers/users_controller.rb:

      class UsersController
    < ApplicationController

        def login
        end

        def verify
          hash_pass =
    Digest::SHA1.hexdigest(params[:user][:hashed_password])[0..39]
          user = User.find(:first,:conditions =>
                            ["username = ?
    and hashed_password = ?",
                       params[:user][:username],
    hash_pass ])
         
    if user
            session['user'] = user
            redirect_to session['initial_uri']
          else
            flash['notice'] = "Bad username/password!"  
            redirect_to :controller => "users",
    :action => "login" 
          end
        end

        def logout
          reset_session 
          # Redirect users to Books#admin,
    which in turn sends them to 
          # Users#login, with a refering url
    of Books#admin:

          redirect_to :controller => "books", :action => "admin"
        end
      end

    Next, provide a mechanism for users to log themselves out if they’re not comfortable letting their session time out on its own. Create a "logout" link with a named route using logout_url:

    app/views/articles/admin.rhtml:

      <h1>Articles Admin</h1>

      <%= link_to "logout", :logout_url %>

    app/views/books/admin.rhtml:

      <h1>Books Admin</h1>

      <%= link_to "logout", :logout_url %>

    Finally, define the "logout" named route with its URL mapping:

    config/routes.rb:

      ActionController::Routing::Routes.draw
    do |map|

        map.logout '/logout', :controller
    => "users", :action => "logout" 

        # Install the default route as the
    lowest priority.
        map.connect ':controller/:action/:id'
      end

    Discussion

    Adding authentication to a site is one of the most common tasks in web development. Almost any site that does anything meaningful requires some level of security, or at least a way to differentiate between site visitors.

    The Rails before_filter lends itself perfectly to the task of access control by invoking an authentication method just before controller actions are executed. Code that is declared as a filter with before_filter has access to all the same objects as the controller, including the request and response objects, and the params and session hashes.

    The solution places the authenticate filter in the Book and Article controllers. Every request to either controller first executes the code in authenticate. This code checks for the existence of a user object in the session hash, under the key of user. If that session key is empty, the URL of the request is stored in its own session key, and the request is redirected to the login method of the User controller.

    The login form submits the username and password to the Login controller, which looks for a match in the database. If a user is found with that username and a matching hashed password, the request is redirected to the URL that was stored in the session earlier.

    When the user wishes to log out, the logout action of the User controller calls reset_session, clearing out all the objects stored in the session. The user is then redirected to the login screen.

    See Also


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

       · This article is an excerpt from the book "Rails Cookbook," published by O'Reilly. We...
     

    Buy this book now. This article is excerpted from chapter four of the Rails Cookbook, written by Rob Orsini (O'Reilly, 2007; ISBN: 0596527314). Check it out at your favorite bookstore. Buy this book now.

    RUBY-ON-RAILS ARTICLES

    - Ruby On Rails: Making Your First Dynamic Site
    - Ruby on Rails: Beginning Rails
    - Ruby: Modules, Mixins, Fixins, and Rails
    - Controlling Information Access with the Rail...
    - URLs, Filters and the Rails Action Controller
    - Flash and the Rails Action Controller
    - Rails Action Controller
    - Dropping and Sorting with AJAX and script.ac...
    - Drag and Drop with script.aculo.us and Rails
    - Introducing script.aculo.us
    - Ruby Classes and Objects
    - Ruby Loops
    - Ruby Conditionals
    - Ruby Operators and Arrays
    - Ruby for the Newbie







    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 2 hosted by Hostway