Kann ich eine Route ohne Authentifizierung bereitstellen?

Gibt es eine Möglichkeit, eine Route zu erstellen, die die Authentifizierung umgeht?

Dies dient der Integration mit Diensten von Drittanbietern.
Die Anforderung besteht darin, dem Dienst eine URL bereitzustellen (Header oder Payloads jeglicher Art werden nicht unterstützt).
Früher war dies möglich, indem man “?api_key=…&api_username=” anhängte, aber diese Option existiert nun nicht mehr.

Die Discourse-Instanz wird von uns gehostet.

Du benötigst ein benutzerdefiniertes Plugin, das eine Route erstellt, die eine Nutzdatenübertragung (Payload) entgegennehmen und darauf reagieren kann. Beachte bitte, dass du, da du den Benutzer nicht authentifizieren kannst, möglicherweise eine Methode benötigst, um die Nutzdaten zu authentifizieren.

Meine Regel lautet: keine anonymen Konten. Daher kann ich nicht auf die Plugin-Routen zugreifen. Was ich benötige, ist eine Möglichkeit, für diesen Szenario eine Route zu erstellen.

Zum Beispiel:

  # Standardmäßig lässt Rails 3.2 die Anfrage mit einer leeren Sitzung durch
  # wir sind hier pedantischer und setzen die Sitzung / current_user auf null
  # und werfen dann eine CSRF-Ausnahme
  def handle_unverified_request
    # HINWEIS: Der API-Schlüssel ist geheim; seine Existenz macht ein CSRF-Token überflüssig
    unless is_api? || is_user_api?
      super
      clear_current_user
      render plain: "[\"BAD CSRF\"]", status: 403
    end
  end

Eine Möglichkeit, während dieses Ablaufs oder des gesamten Authentifizierungsprozesses zu benachrichtigen, dass ein Controller und eine Aktion, die über Parameter empfangen werden (die automatisch gesetzt werden, wenn Sie eine Route aufrufen), alles umgehen und die Route ausführen können.

Ich bin mir nicht vollständig darüber im Klaren, wie alles funktioniert, aber da es eine Option für anonymen Zugriff gibt, bin ich sicher, dass es eine Möglichkeit gibt, dies zu realisieren.

Dies würde es ermöglichen, dass Nutzer die Nutzlast bei Bedarf verschlüsseln können, aber für das Aktualisieren des Systems mit allgemeinen Informationen wäre es nützlich.

Über ein Plugin können Sie Ihre neue Route zu DiscoursePluginRegistry.api_parameter_routes hinzufügen, sodass Sie weiterhin API-Anmeldeinformationen über Abfrageparameter übergeben können:

Sie benötigen auch das folgende Stanza

skip_before_action :redirect_to_login_if_required

in Ihrem benutzerdefinierten Controller, falls es sich um eine Seite handelt, die eine Anmeldung erfordert.

Ok. Also überschreibe diese Methode und überspringe die Aktion. Ich werde es versuchen und euch Bescheid geben, falls es klappt.

# Standardmäßig erlauben wir nur Header für das Senden von API-Anmeldeinformationen.
  # In einigen Szenarien ist es jedoch unerlässlich, diese über URL-Parameter zu senden,
  # daher müssen wir einige Ausnahmen hinzufügen.
  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 'Erlaubt'
      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

Ich habe dies nur getan, um die Git-Diffs für die Zukunft zu minimieren.

Außerdem mein Controller:

# 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

Jetzt prüft der Endpunkt also weder Parameter noch Header-Anmeldedaten.

Wie stelle ich sicher, dass er den bereitgestellten API-Schlüssel prüft und nur Zugriff gewährt, wenn er gültig ist? (So wie es früher funktioniert hat)

@riking @blake?

Ich glaube, das Hinzufügen von requires_login zu deinem Controller wird den Trick machen. Schau dir einige der anderen Controller in app/controllers an, um Beispiele zu finden.

Das hat leider nicht funktioniert :slight_smile:

class MExposedController < ::ApplicationController

  requires_login

  skip_before_action :redirect_to_login_if_required, raise: false

Completed 403 Forbidden

{"errors":["Sie müssen eingeloggt sein, um dies zu tun."],"error_type":"not_logged_in"}

Dies wurde innerhalb eines Plugins deklariert.

Und du hast deine API-Anmeldedaten über Query-Parameter übergeben? Wenn ja, bedeutet das, dass deine Route wahrscheinlich nicht korrekt zur Umgehung hinzugefügt wurde, um API-Anmeldedaten in Query-Parametern zuzulassen. Möglicherweise musst du die Umgehungslogik debuggen und prüfen, ob deine Route jemals hinzugefügt wurde.

Na, es funktioniert und umgeht alles ohne requires_login. Ich habe geschrieben, wie ich das gemacht habe. Hmm…

Es scheint, dass ich es nur ohne Anmeldeinformationen zum Laufen bringen kann. Na gut, zumindest habe ich mein ursprüngliches Problem gelöst.