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 和選項呼叫登入程序。
如果找到 token,則傳回 login_procedure
的傳回值。如果找不到 token,則傳回 nil
。
參數
-
controller
- 目前要求的ActionController::Base
個體。 -
login_procedure
- 如果有 token,則呼叫的程序。程序應使用兩個引數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 和選項。授權標頭的值預計會以 "Token"
或 "Bearer"
為前綴。標頭若長的像這樣
Authorization: Token token="abc", nonce="def"
那麼回傳的 token 會是 "abc"
而選項會是 {nonce: "def}"}
。
若存在 token,則回傳 [字串,雜湊]
的 陣列
。若找不到 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