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 提要和 XML API
受 HTTP 令牌身份验证的保护。常规的 HTML 界面受会话方法保护
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) 链接
如果存在令牌授权头,则使用当前令牌和选项调用登录过程。
如果找到令牌,则返回login_procedure
的返回值。如果没有找到令牌,则返回nil
。
参数
-
controller
-ActionController::Base
当前请求的实例。 -
login_procedure
- 如果存在令牌,则要调用的 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 头,让客户端知道需要令牌。
不返回任何内容。
参数
-
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"
或"Bearer"
为前缀。如果头看起来像这样
Authorization: Token token="abc", nonce="def"
那么返回的令牌是"abc"
,选项是{nonce: "def"}
。
如果存在令牌,则返回[String, Hash]
的Array
。如果没有找到令牌,则返回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