модуль ActionController::HttpAuthentication::Token
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] Константы
- AUTHN_PAIR_DELIMITERS
- TOKEN_KEY
- TOKEN_REGEX
Открытые методы экземпляра
# 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 Если заголовок Authorization содержит токен, вызовите процедуру входа в систему с текущим токеном и параметрами.
Возвращает результат выполнения login_procedure если токен найден. Возвращает nil если токен не найден.
Parameters
-
controller- экземплярActionController::Baseдля текущего запроса. -
login_procedure- Процедура, вызываемая, если токен присутствует. Процедура должна принимать два аргумента:authenticate(controller) { |token, options| ... }
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 558
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 Устанавливает заголовок WWW-Authenticate, чтобы сообщить клиенту, что ожидается токен.
Не возвращает ничего.
Parameters
-
controller- экземплярActionController::Baseдля исходящего ответа. -
realm-Stringобласть, используемая в заголовке.
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 542
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 Кодирует указанный токен и параметры в значение заголовка Authorization.
Возвращает String.
Parameters
# 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 и преобразует его в массив параметров.
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 522
def raw_params(auth)
_raw_params = auth.sub(TOKEN_REGEX, "").split(WHITESPACED_AUTHN_PAIR_DELIMITERS)
_raw_params.reject!(&:empty?)
if !_raw_params.first&.start_with?(TOKEN_KEY)
_raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
end
_raw_params
end Этот метод принимает тело авторизации и разделяет пары ключ-значение с помощью стандартизированных разделителей :, ;, или \t, определённых в AUTHN_PAIR_DELIMITERS.
# 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 Удаляет символы " , обрамляющие значение.
# 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 Парсит токен и параметры из заголовка Authorization. Ожидается, что значение заголовка Authorization имеет префикс "Token" или "Bearer". Если заголовок выглядит так:
Authorization: Token token="abc", nonce="def"
Тогда возвращаемый токен - "abc", а параметры - {nonce: "def"}.
Возвращает Array из [String, Hash] если токен присутствует. Возвращает nil если токен не найден.
Parameters
-
request- экземплярActionDispatch::Requestс текущими заголовками.
# 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
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.