Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/trunk/actionpack/lib/action_controller/http_authentication.rb

Revision 9134, 4.2 kB (checked in by david, 7 months ago)

Removed the default .htaccess configuration as there are so many good deployment options now (kept it as an example in README) [DHH]

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.