модуль ActionController::HttpAuthentication::Token
Обеспечивает простую реализацию аутентификации HTTP токеном.
Простой пример использования токена:
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|
token == TOKEN
end
end
end
Вот пример более продвинутого использования токена, где аутентификация по HTTP-токенам защищает только ленты Atom и XML API, а обычный интерфейс HTML защищается с помощью сессий:
class ApplicationController < ActionController::Base
before_action :set_account, :authenticate
protected
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
get(
"/notes/1.xml", nil,
'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Token.encode_credentials(users(:dhh).token)
)
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
Публичные методы экземпляра
Если в заголовке Authorization присутствует токен, вызовите процедуру входа с данным токеном и опциями.
- controller
-
Экземпляр ActionController::Base для текущего запроса.
- login_procedure
-
Процедура, вызываемая при наличии токена. Процедура должна принимать два аргумента:
authenticate(controller) { |token, options| ... }
Возвращает значение, возвращаемое login_procedure при нахождении токена. Возвращает nil при отсутствии токена.
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 438
def authenticate(controller, &login_procedure)
token, options = token_and_options(controller.request)
unless token.blank?
login_procedure.call(token, options)
end
end Устанавливает WWW-Authenticate, чтобы сообщить клиенту о необходимости токена.
controller - экземпляр ActionController::Base для исходящего ответа. realm - строка области, которая используется в заголовке.
Не возвращает ничего.
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 508
def authentication_request(controller, realm)
controller.headers["WWW-Authenticate"] = %Q(Token realm="#{realm.gsub(/"/, "")}")
controller.__send__ :render, :text => "HTTP Token: Access denied.\n", :status => :unauthorized
end Кодирует заданный токен и опции в значение заголовка Authorization.
token - строка токена. options - необязательный словарь опций.
Возвращает строку.
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 495
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 Преобразует #raw_params в массив параметров
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 467
def params_array_from(raw_params)
raw_params.map { |param| param.split /=(.+)?/ }
end Этот метод принимает тело авторизации и разбивает пары ключ-значение по стандартным разделителям `:`, `;` или `t`, определенным в `AUTHN_PAIR_DELIMITERS`.
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 479
def raw_params(auth)
_raw_params = auth.sub(TOKEN_REGEX, '').split(/\s*#{AUTHN_PAIR_DELIMITERS}\s*/)
if !(_raw_params.first =~ %r{\A#{TOKEN_KEY}})
_raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
end
_raw_params
end Удаляет символы `“` обертывающие значение.
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 472
def rewrite_param_values(array_params)
array_params.each { |param| (param[1] || "").gsub! /^"|"$/, '' }
end Извлекает токен и опции из заголовка авторизации. Если заголовок выглядит так:
Authorization: Token token="abc", nonce="def"
Тогда возвращаемый токен — «abc», а опции — {nonce: «def»}
request - экземпляр ActionDispatch::Request с текущими заголовками.
Возвращает массив [String, Hash], если токен присутствует. Возвращает null, если токен не найден.
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 454
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 # File actionpack/lib/action_controller/metal/http_authentication.rb, line 462 def token_params_from(auth) rewrite_param_values params_array_from raw_params auth end
© 2004–2016 David Heinemeier Hansson
Licensed under the MIT License.