인증 없이 라우트를 생성할 수 있는 방법이 있을까요?
이것은 제3자 서비스와 통합하는 데 사용됩니다.
요건은 해당 서비스에 URL을 제공하는 것입니다(헤더나 페이로드의 어떤 유형도 지원되지 않음).
이전에는 "?api_key=…&api_username="을 붙여서 가능했지만, 지금은 더 이상 사용할 수 없습니다.
Discourse 인스턴스는 우리가 직접 호스팅하고 있습니다.
인증 없이 라우트를 생성할 수 있는 방법이 있을까요?
이것은 제3자 서비스와 통합하는 데 사용됩니다.
요건은 해당 서비스에 URL을 제공하는 것입니다(헤더나 페이로드의 어떤 유형도 지원되지 않음).
이전에는 "?api_key=…&api_username="을 붙여서 가능했지만, 지금은 더 이상 사용할 수 없습니다.
Discourse 인스턴스는 우리가 직접 호스팅하고 있습니다.
페이로드를 받아서 처리할 수 있는 라우트를 생성하는 커스텀 플러그인이 필요합니다. 사용자가 인증되지 않으므로, 페이로드를 인증할 수 있는 방법이 필요할 수 있다는 점을 유념해 주세요.
내 원칙은 익명 계정을 허용하지 않는 것입니다. 그래서 플러그인 라우트에 접근할 수 없습니다. 이 유형의 시나리오를 위해 라우트가 생성될 수 있는 방법이 필요합니다.
예를 들어,
# 기본 Rails 3.2는 빈 세션으로 요청을 통과시킵니다 # 여기서는 더 엄격하게 세션 / current_user를 null로 처리한 # 다음 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 자격 증명을 계속 전달할 수 있습니다:
로그인 필수 사이트인 경우, 사용자 정의 컨트롤러에도 다음 스탠사가 필요합니다.
skip_before_action :redirect_to_login_if_required
알겠습니다. 해당 메서드를 오버라이드해서 액션을 건너뛰세요. 성공하면 알려주세요.
# 기본적으로는 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 diff를 최소화하기 위해서입니다.
또한, 제 컨트롤러는 다음과 같습니다:
# 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
컨트롤러에 requires_login을 추가하면 해결될 것 같습니다. app/controllers의 다른 컨트롤러들을 참고해 보세요.
음, 그 방법은 효과가 없었네요 ![]()
class MExposedController < ::ApplicationController
requires_login
skip_before_action :redirect_to_login_if_required, raise: false
Completed 403 Forbidden
{"errors":["You need to be logged in to do that."],"error_type":"not_logged_in"}
이것은 플러그인 내부에서 선언되어 있습니다.
API 자격 증명을 쿼리 매개변수로 전달하셨나요? 그렇다면 API 자격 증명을 쿼리 매개변수로 허용하도록 우회(bypass) 목록에 해당 라우트가 올바르게 추가되지 않은 것일 수 있습니다. 우회 로직을 디버깅하여 해당 라우트가 실제로 추가되었는지 확인해 보시는 것이 좋습니다.
음, 잘 동작하긴 하고 requires_login 없이 모든 것을 우회하긴 해. 내가 어떻게 했는지 올려놨거든. 음..
자격 증명 없이만 작동하는 것 같습니다. 뭐, 어쨌든 처음에 겪었던 문제는 해결했으니 다행입니다.