Есть ли способ создать маршрут, который обходит аутентификацию?
Это используется для интеграции со сторонними сервисами.
Требование — предоставить сервису URL (заголовки или полезные данные любого типа не поддерживаются).
Раньше это было возможно, добавляя “?api_key=…&api_username=”, но теперь этот вариант удалён.
Вам потребуется специальный плагин, который создаст маршрут, способный принимать полезную нагрузку и обрабатывать её. Обратите внимание: поскольку вы не можете аутентифицировать пользователя, вам, возможно, понадобится способ аутентификации самой полезной нагрузки.
Мое правило — никаких анонимных аккаунтов. Поэтому я не могу получить доступ к маршрутам плагинов. Мне нужен способ создать маршрут для такого сценария.
Например,
# В Rails 3.2 по умолчанию запрос проходит с пустой сессией
# Мы же здесь более педантичны: обнуляем сессию / current_user
# и затем выбрасываем исключение CSRF
def handle_unverified_request
# ПРИМЕЧАНИЕ: API-ключ является секретом; его наличие отменяет необходимость в CSRF-токене
unless is_api? || is_user_api?
super
clear_current_user
render plain: "[\"BAD CSRF\"]", status: 403
end
end
Мне нужен способ уведомить систему в ходе этого процесса или всего процесса аутентификации, что контроллер и действие, полученные через параметры (устанавливаются автоматически при вызове маршрута), могут обойти все проверки и выполнить маршрут.
Я не до конца понимаю, как всё работает, но поскольку есть опция анонимного доступа, я уверен, что способ это сделать существует.
Это позволило бы людям при необходимости шифровать полезную нагрузку, а для обновления системы общей информацией было бы очень полезно.
С помощью плагина вы можете добавить свой новый маршрут в DiscoursePluginRegistry.api_parameter_routes, чтобы продолжать передавать учетные данные API через параметры запроса:
# По умолчанию мы разрешаем отправку учетных данных API только через заголовки
# Однако в некоторых сценариях критически важно передавать их через параметры URL,
# поэтому нам нужно добавить некоторые исключения
def api_parameter_allowed?
request_method = @env["REQUEST_METHOD"]&.downcase&.to_sym
request_format = @env['action_dispatch.request.formats']&.first&.symbol
path_params = @env['action_dispatch.request.path_parameters']
request_route = "#{path_params[:controller]}##{path_params[:action]}" if path_params
if 'm_exposed#endpoint' == request_route && request_method == 'get'
puts 'Allowed'
return true
end
PARAMETER_API_PATTERNS.any? do |p|
(p[:method] == "*" || Array(p[:method]).include?(request_method)) &&
(p[:format] == "*" || Array(p[:format]).include?(request_format)) &&
(p[:route] == "*" || Array(p[:route]).include?(request_route))
end
end
Я сделал это, чтобы минимизировать будущие изменения в git.
Также мой контроллер:
# frozen_string_literal: true
class MExposedController < ::ApplicationController
skip_before_action :redirect_to_login_if_required, raise: false
def endpoint
render json: { state: "hello world" }
end
end
А вы передали свои учётные данные API через параметры запроса? Если да, то, скорее всего, ваш маршрут не был правильно добавлен в список исключений для разрешения учётных данных API в параметрах запроса. Возможно, вам потребуется отладить логику исключений и проверить, был ли ваш маршрут вообще добавлен.