C’è qualche modo per creare una rotta che bypassi l’autenticazione?
Questo viene utilizzato per l’integrazione con servizi di terze parti.
Il requisito consiste nel fornire al servizio un URL (non sono supportati né header né payload di alcun tipo).
In precedenza era possibile aggiungendo “?api_key=…&api_username=” ma tale opzione non è più disponibile.
Avresti bisogno di un plugin personalizzato che crei una rotta in grado di accettare un payload e agire di conseguenza. Tieni presente che, poiché non sei in grado di autenticare l’utente, potresti aver bisogno di un modo per autenticare il payload.
La mia regola è: nessun account anonimo. Quindi non posso accedere alle rotte del plugin. Ciò di cui avrei bisogno è un modo per creare una rotta per questo tipo di scenario.
Ad esempio,
# Rails 3.2 predefinito lascia passare la richiesta con una sessione vuota
# qui siamo più pedanti e annulliamo la sessione / current_user
# e poi solleviamo un'eccezione CSRF
def handle_unverified_request
# NOTA: la chiave API è segreta; averla invalida la necessità di un token CSRF
unless is_api? || is_user_api?
super
clear_current_user
render plain: "[\"BAD CSRF\"]", status: 403
end
end
Un modo per notificare, durante questo flusso o l’intero flusso di autenticazione, che un controller e un’azione ricevuti tramite parametri (impostati automaticamente quando si chiama una rotta) possono bypassare tutto ed eseguire la rotta.
Non sono pienamente consapevole di come funzioni tutto, ma dato che esiste un’opzione di accesso anonimo, sono sicuro che ci sia un modo per farlo.
Ciò permetterebbe alle persone di crittografare il payload se necessario, ma per l’aggiornamento del sistema con informazioni generiche sarebbe utile.
Tramite un plugin, puoi aggiungere la tua nuova rotta a DiscoursePluginRegistry.api_parameter_routes in modo da poter continuare a passare le credenziali API tramite parametri di query:
# Di default permettiamo solo le intestazioni per l'invio delle credenziali API
# Tuttavia, in alcuni scenari è essenziale inviarle tramite parametri URL
# quindi dobbiamo aggiungere alcune eccezioni
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 'Consentito'
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
Ho fatto questo solo per minimizzare le differenze git future.
Inoltre, il mio 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
Credo che aggiungere requires_login al tuo controller farà al caso tuo. Dai un’occhiata ad alcuni degli altri controller in app/controllers per degli esempi.
E hai passato le tue credenziali API tramite parametri di query? Se sì, significa che la tua rotta probabilmente non è stata aggiunta correttamente al bypass per consentire le credenziali API nei parametri di query. Potresti dover eseguire il debug della logica di bypass e verificare se la tua rotta è mai stata aggiunta.