Spec-Zone.ru › Ruby on Rails 5.1

модуль 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|
        # Compare the tokens in a time-constant manner, to mitigate
        # timing attacks.
        ActiveSupport::SecurityUtils.secure_compare(
          ::Digest::SHA256.hexdigest(token),
          ::Digest::SHA256.hexdigest(TOKEN)
        )
      end
    end
end

Вот более сложный пример с токеном, где аутентификацией по HTTP-токенам защищены только Atom-каналы и XML API, а обычный 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
  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

Открытые методы экземпляров

authenticate(controller, &login_procedure) Показать исходный код
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 441
def authenticate(controller, &login_procedure)
  token, options = token_and_options(controller.request)
  unless token.blank?
    login_procedure.call(token, options)
  end
end

Если заголовок Authorization содержит токен, вызовите процедуру входа в систему с предоставленным токеном и опциями.

controller

Экземпляр ActionController::Base для текущего запроса.

login_procedure

Процедура, которая вызывается, если токен есть. Процедура должна принимать два аргумента:

authenticate(controller) { |token, options| ... }

Возвращает значение, возвращённое login_procedure если токен найден. Возвращает nil если токен не найден.

authentication_request(controller, realm, message = nil) Показать исходный код
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 513
def authentication_request(controller, realm, message = nil)
  message ||= "HTTP Token: Access denied.\n"
  controller.headers["WWW-Authenticate"] = %Q(Token realm="#{realm.tr('"'.freeze, "".freeze)}")
  controller.__send__ :render, plain: message, status: :unauthorized
end

Устанавливает заголовок WWW-Authenticate, чтобы сообщить клиенту, что требуется токен.

controller - экземпляр ActionController::Base для исходящего ответа. realm - строка области для использования в заголовке.

Не возвращает ничего.

encode_credentials(token, options = {}) Показать исходный код
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 500
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.

token - строка токен. options - необязательный хэш опций.

Возвращает строку.

params_array_from(raw_params) Показать исходный код
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 472
def params_array_from(raw_params)
  raw_params.map { |param| param.split /=(.+)?/ }
end

Принимает #raw_params и преобразует его в массив параметров.

raw_params(auth) Показать исходный код
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 484
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

Этот метод принимает тело авторизации и разделяет пары ключ-значение по стандартным разделителям :, ;, или \t, определённых в AUTHN_PAIR_DELIMITERS.

rewrite_param_values(array_params) Показать исходный код
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 477
def rewrite_param_values(array_params)
  array_params.each { |param| (param[1] || "").gsub! /^"|"$/, "" }
end

Удаляет символы " , которые обрамляют значение.

token_and_options(request) Показать исходный код
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 459
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"}

request - экземпляр ActionDispatch::Request с текущими заголовками.

Возвращает Array [String, Hash], если токен найден. Возвращает nil если токен не найден.

token_params_from(auth) Показать исходный код
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 467
def token_params_from(auth)
  rewrite_param_values params_array_from raw_params auth
end

© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API