root/trunk/actionpack/lib/action_controller/http_authentication.rb
| Revision 9134, 4.2 kB (checked in by david, 7 months ago) |
|---|
| Line | |
|---|---|
| 1 | module ActionController |
| 2 | module HttpAuthentication |
| 3 | # Makes it dead easy to do HTTP Basic authentication. |
| 4 | # |
| 5 | # Simple Basic example: |
| 6 | # |
| 7 | # class PostsController < ApplicationController |
| 8 | # USER_NAME, PASSWORD = "dhh", "secret" |
| 9 | # |
| 10 | # before_filter :authenticate, :except => [ :index ] |
| 11 | # |
| 12 | # def index |
| 13 | # render :text => "Everyone can see me!" |
| 14 | # end |
| 15 | # |
| 16 | # def edit |
| 17 | # render :text => "I'm only accessible if you know the password" |
| 18 | # end |
| 19 | # |
| 20 | # private |
| 21 | # def authenticate |
| 22 | # authenticate_or_request_with_http_basic do |user_name, password| |
| 23 | # user_name == USER_NAME && password == PASSWORD |
| 24 | # end |
| 25 | # end |
| 26 | # end |
| 27 | # |
| 28 | # |
| 29 | # Here is a more advanced Basic example where only Atom feeds and the XML API is protected by HTTP authentication, |
| 30 | # the regular HTML interface is protected by a session approach: |
| 31 | # |
| 32 | # class ApplicationController < ActionController::Base |
| 33 | # before_filter :set_account, :authenticate |
| 34 | # |
| 35 | # protected |
| 36 | # def set_account |
| 37 | # @account = Account.find_by_url_name(request.subdomains.first) |
| 38 | # end |
| 39 | # |
| 40 | # def authenticate |
| 41 | # case request.format |
| 42 | # when Mime::XML, Mime::ATOM |
| 43 | # if user = authenticate_with_http_basic { |u, p| @account.users.authenticate(u, p) } |
| 44 | # @current_user = user |
| 45 | # else |
| 46 | # request_http_basic_authentication |
| 47 | # end |
| 48 | # else |
| 49 | # if session_authenticated? |
| 50 | # @current_user = @account.users.find(session[:authenticated][:user_id]) |
| 51 | # else |
| 52 | # redirect_to(login_url) and return false |
| 53 | # end |
| 54 | # end |
| 55 | # end |
| 56 | # end |
| 57 | # |
| 58 | # |
| 59 | # In your integration tests, you can do something like this: |
| 60 | # |
| 61 | # def test_access_granted_from_xml |
| 62 | # get( |
| 63 | # "/notes/1.xml", nil, |
| 64 | # :authorization => ActionController::HttpAuthentication::Basic.encode_credentials(users(:dhh).name, users(:dhh).password) |
| 65 | # ) |
| 66 | # |
| 67 | # assert_equal 200, status |
| 68 | # end |
| 69 | # |
| 70 | # |
| 71 | # On shared hosts, Apache sometimes doesn't pass authentication headers to |
| 72 | # FCGI instances. If your environment matches this description and you cannot |
| 73 | # authenticate, try this rule in your Apache setup: |
| 74 | # |
| 75 | # RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L] |
| 76 | module Basic |
| 77 | extend self |
| 78 | |
| 79 | module ControllerMethods |
| 80 | def authenticate_or_request_with_http_basic(realm = "Application", &login_procedure) |
| 81 | authenticate_with_http_basic(&login_procedure) || request_http_basic_authentication(realm) |
| 82 | end |
| 83 | |
| 84 | def authenticate_with_http_basic(&login_procedure) |
| 85 | HttpAuthentication::Basic.authenticate(self, &login_procedure) |
| 86 | end |
| 87 | |
| 88 | def request_http_basic_authentication(realm = "Application") |
| 89 | HttpAuthentication::Basic.authentication_request(self, realm) |
| 90 | end |
| 91 | end |
| 92 | |
| 93 | def authenticate(controller, &login_procedure) |
| 94 | unless authorization(controller.request).blank? |
| 95 | login_procedure.call(*user_name_and_password(controller.request)) |
| 96 | end |
| 97 | end |
| 98 | |
| 99 | def user_name_and_password(request) |
| 100 | decode_credentials(request).split(/:/, 2) |
| 101 | end |
| 102 | |
| 103 | def authorization(request) |
| 104 | request.env['HTTP_AUTHORIZATION'] || |
| 105 | request.env['X-HTTP_AUTHORIZATION'] || |
| 106 | request.env['X_HTTP_AUTHORIZATION'] || |
| 107 | request.env['REDIRECT_X_HTTP_AUTHORIZATION'] |
| 108 | end |
| 109 | |
| 110 | def decode_credentials(request) |
| 111 | ActiveSupport::Base64.decode64(authorization(request).split.last || '') |
| 112 | end |
| 113 | |
| 114 | def encode_credentials(user_name, password) |
| 115 | "Basic #{ActiveSupport::Base64.encode64("#{user_name}:#{password}")}" |
| 116 | end |
| 117 | |
| 118 | def authentication_request(controller, realm) |
| 119 | controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.gsub(/"/, "")}") |
| 120 | controller.send! :render, :text => "HTTP Basic: Access denied.\n", :status => :unauthorized |
| 121 | end |
| 122 | end |
| 123 | end |
| 124 | end |
Note: See TracBrowser for help on using the browser.