인증 없이 라우트를 노출할 수 있나요?

인증 없이 라우트를 생성할 수 있는 방법이 있을까요?

이것은 제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

이제 엔드포인트가 파라미터나 헤더의 인증 정보를 확인하지 않습니다.

API 키가 유효한 경우에만 액세스를 허용하도록 어떻게 설정할 수 있을까요? (예전처럼 동작하도록)

@riking @blake ?

컨트롤러에 requires_login을 추가하면 해결될 것 같습니다. app/controllers의 다른 컨트롤러들을 참고해 보세요.

음, 그 방법은 효과가 없었네요 :slight_smile:

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 없이 모든 것을 우회하긴 해. 내가 어떻게 했는지 올려놨거든. 음..

자격 증명 없이만 작동하는 것 같습니다. 뭐, 어쨌든 처음에 겪었던 문제는 해결했으니 다행입니다.