There are a number of pages that cover the topic of authentication—see Authentication for an overview.
If you’re looking for something simple and easy, Coda Hale has provided a plugin: simple_http_auth.
Within Rails 2, simple_http_auth is part of the rails kernel
Begin with an Account model. (You can call it User or Member or whatever – just update the controller code below to reflect this.)
This model should be created with (at minimum):
create_table :accounts do |t|
t.column 'login', :string
t.column 'password', :string
end
The code for this model should include:
require 'digest/sha1'
class Account < ActiveRecord::Base
def password=(str)
write_attribute("password", Digest::SHA1.hexdigest(str))
end
def password
"********"
end
def self.authenticate(l, p)
find_by_login_and_password(l, Digest::SHA1.hexdigest(p))
end
end
Next, you should add these private methods to your ApplicationController:
private
def authorise
# Log in using session data if it exists.
if id = session["account_id"]
@account = Account.find(id) and return true
end
# Otherwise log in from authentication data sent in request header.
login, password = get_auth_data
if login and password and @account = Account.authenticate(login, password)
session["account_id"] = @account.id
return true
end
# If no auth data, or wrong auth data, issue a challenge.
response.headers["Status"] = "Unauthorized"
response.headers["WWW-Authenticate"] = 'Basic realm="Realm"'
render(:text => "Authentication required", :status => 401)
end
def deauthorise
session.delete("account_id")
end
def get_auth_data
auth_data = nil
[
'REDIRECT_REDIRECT_X_HTTP_AUTHORIZATION',
'REDIRECT_X_HTTP_AUTHORIZATION',
'X-HTTP_AUTHORIZATION',
'HTTP_AUTHORIZATION'
].each do |key|
if request.env.has_key?(key)
auth_data = request.env[key].to_s.split
break
end
end
if auth_data && auth_data[0] == 'Basic'
return Base64.decode64(auth_data[1]).split(':')[0..1]
end
end
Finally, in any controller where you want to require HTTP Basic Authentication, use authorise as a before_filter:
before_filter :authorise
If you want to let people log out without closing their browser, create an action in a controller that calls the deauthorise method.
If you are using Apache and mod_fastcgi, this method will likely not work out of the box. Apache does not allow CGI scripts access to HTTP authorization headers by default. You will need to configure FastCGI to pass the Authorization header to your scripts . Short version: add -pass-header Authorization to the FastCgiServer startup directive, or FastCgiConfig -pass-header Authorization, for Apache 2, or -pass-header HTTP_AUTHORIZATION for Apache 1. For this, you will need access to apache’s config file.
If you cannot change the mod_fastcgi configuration, you may be able to use mod_rewrite to pass the Authorization header to Rails. Modify the RewriteRule that rewrites to the dispatcher to:
RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
The Authorization header will now be available in request.env[‘X-HTTP_AUTHORIZATION’]. Depending on your mod_rewrite configuration, you may find the environment variable gets prefixed with REDIRECT_ one or more times.
Apache2 does not pass HTTP authentication headers
to CGI/FCGID scripts, so the only way is to authenticate via Apache (htaccess) and check request.env[“REMOTE_USER”] for already validated user.
category: Howto