HTTP Token 认证¶ ↑
简单 Token 示例¶ ↑
class PostsController < ApplicationController TOKEN = "secret" before_action :authenticate, except: [ :index ] def index render plain: "Everyone can see me!" end def edit render plain: "I'm only accessible if you know the password" end private def authenticate authenticate_or_request_with_http_token do |token, options| # Compare the tokens in a time-constant manner, to mitigate # timing attacks. ActiveSupport::SecurityUtils.secure_compare(token, TOKEN) end end end
这是一个更高级的 Token 示例,其中只有 Atom feed 和 XML API 受 HTTP token 认证保护。常规的 HTML 接口受 session 机制保护。
class ApplicationController < ActionController::Base before_action :set_account, :authenticate private def set_account @account = Account.find_by(url_name: request.subdomains.first) end def authenticate case request.format when Mime[:xml], Mime[:atom] if user = authenticate_with_http_token { |t, o| @account.users.authenticate(t, o) } @current_user = user else request_http_token_authentication end else if session_authenticated? @current_user = @account.users.find(session[:authenticated][:user_id]) else redirect_to(login_url) and return false end end end end
在您的集成测试中,您可以这样做:
def test_access_granted_from_xml authorization = ActionController::HttpAuthentication::Token.encode_credentials(users(:dhh).token) get "/notes/1.xml", headers: { 'HTTP_AUTHORIZATION' => authorization } assert_equal 200, status end
在共享主机上,Apache 有时不会将认证头传递给 FCGI 实例。如果您的环境符合此描述并且您无法进行身份验证,请尝试在您的 Apache 设置中添加此规则:
RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
- A
- E
- P
- R
- T
常量
| AUTHN_PAIR_DELIMITERS | = | /(?:,|;|\t)/ |
| TOKEN_KEY | = | "token=" |
| TOKEN_REGEX | = | /^(Token|Bearer)\s+/ |
实例公共方法
authenticate(controller, &login_procedure) 链接
如果存在 token Authorization 头,则使用存在的 token 和选项调用 login procedure。
如果找到 token,则返回 login_procedure 的返回值。如果没有找到 token,则返回 nil。
参数¶ ↑
-
controller- 当前请求的ActionController::Base实例。 -
login_procedure- 如果存在 token,则调用此 Proc。Proc 应接受两个参数:authenticate(controller) { |token, options| ... }
来源: 显示 | 在 GitHub 上
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 472 def authenticate(controller, &login_procedure) token, options = token_and_options(controller.request) unless token.blank? login_procedure.call(token, options) end end
authentication_request(controller, realm, message = nil) 链接
设置一个 WWW-Authenticate 头,让客户端知道需要 token。
不返回任何内容。
参数¶ ↑
-
controller- 外发响应的ActionController::Base实例。 -
realm- 头中使用的String领域。
来源: 显示 | 在 GitHub 上
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 555 def authentication_request(controller, realm, message = nil) message ||= "HTTP Token: Access denied.\n" controller.headers["WWW-Authenticate"] = %(Token realm="#{realm.tr('"', "")}") controller.__send__ :render, plain: message, status: :unauthorized end
encode_credentials(token, options = {}) 链接
来源: 显示 | 在 GitHub 上
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 539 def encode_credentials(token, options = {}) values = ["#{TOKEN_KEY}#{token.to_s.inspect}"] + options.map do |key, value| "#{key}=#{value.to_s.inspect}" end "Token #{values * ", "}" end
params_array_from(raw_params) 链接
接收 raw_params 并将其转换为参数数组。
来源: 显示 | 在 GitHub 上
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 507 def params_array_from(raw_params) raw_params.map { |param| param.split %r/=(.+)?/ } end
raw_params(auth) 链接
此方法接受一个授权主体,并根据 AUTHN_PAIR_DELIMITERS 中定义的标准 :、; 或 \t 分隔符将其拆分为键值对。
来源: 显示 | 在 GitHub 上
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 519 def raw_params(auth) _raw_params = auth.sub(TOKEN_REGEX, "").split(AUTHN_PAIR_DELIMITERS).map(&:strip) _raw_params.reject!(&:empty?) if !_raw_params.first&.start_with?(TOKEN_KEY) _raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}" end _raw_params end
rewrite_param_values(array_params) 链接
此方法移除包裹在值周围的 " 字符。
来源: 显示 | 在 GitHub 上
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 512 def rewrite_param_values(array_params) array_params.each { |param| (param[1] || +"").gsub! %r/^"|"$/, "" } end
token_and_options(request) 链接
从 token Authorization 头中解析 token 和选项。Authorization 头的值预期带有 "Token" 或 "Bearer" 前缀。如果头看起来像这样:
Authorization: Token token="abc", nonce="def"
那么返回的 token 是 "abc",选项是 {nonce: "def"}。
如果存在 token,则返回 [String, Hash] 的 Array。如果不存在 token,则返回 nil。
参数¶ ↑
-
request- 当前头的ActionDispatch::Request实例。
来源: 显示 | 在 GitHub 上
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 494 def token_and_options(request) authorization_request = request.authorization.to_s if authorization_request[TOKEN_REGEX] params = token_params_from authorization_request [params.shift[1], Hash[params].with_indifferent_access] end end
token_params_from(auth) 链接
来源: 显示 | 在 GitHub 上
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 502 def token_params_from(auth) rewrite_param_values params_array_from raw_params auth end