Questa pagina si applica ad Apigee e Apigee hybrid.
Visualizza la documentazione di Apigee Edge.
CORS (Cross-Origin Resource Sharing) è un meccanismo standard che consente alle chiamate XMLHttpRequest (XHR) di JavaScript eseguite in una pagina web di interagire con le risorse di domini diversi da quello di origine. CORS è una soluzione comunemente implementata per i criteri della stessa origine applicati da tutti i browser. Ad esempio, se effettui una chiamata XHR all'API Twitter dal codice JavaScript eseguito nel browser, la chiamata non andrà a buon fine. Questo perché il dominio che pubblica la pagina nel browser non è lo stesso del dominio che pubblica l'API Twitter. CORS fornisce una soluzione a questo problema consentendo ai server di attivare la condivisione delle risorse tra origini se vogliono fornire questa funzionalità.
Caso d'uso tipico per CORS
Il seguente codice JQuery chiama un servizio target fittizio. Se eseguita nel contesto di un browser (una pagina web), la chiamata non andrà a buon fine a causa del criterio della stessa origine:
<script> var url = "http://service.example.com"; $(document).ready(function(){ $("button").click(function(){ $.ajax({ type:"GET", url:url, async:true, dataType: "json", success: function(json) { // Parse the response. // Do other things. }, error: function(xhr, status, err) { // This is where we end up! } }); }); }); </script>
Una soluzione a questo problema è creare un proxy API Apigee che chiami l'API di servizio sul backend. Ricorda che Apigee si trova tra il client (in questo caso un browser) e l'API di backend (il servizio). Poiché il proxy API viene eseguito sul server e non in un browser, è in grado di chiamare il servizio correttamente. A questo punto, non devi fare altro che collegare le intestazioni CORS alla risposta TargetEndpoint. Se il browser supporta CORS, queste intestazioni indicano al browser che può allentare i suoi criteri della stessa origine, consentendo il buon esito della chiamata all'API cross-origin.
Una volta creato il proxy con il supporto CORS, puoi chiamare l'URL del proxy API anziché il servizio di backend nel codice lato client. Ad esempio:
<script> var url = "http://myorg-test.apigee.net/v1/example"; $(document).ready(function(){ $("button").click(function(){ $.ajax({ type:"GET", url:url, async:true, dataType: "json", success: function(json) { // Parse the response. // Do other things. }, error: function(xhr, status, err) { // This time, we do not end up here! } }); }); }); </script>
Collegamento del criterio CORS al PreFlow della richiesta di ProxyEndpoint
Collegamento di un criterio Aggiungi CORS a un nuovo proxy API
Puoi aggiungere il supporto CORS a un proxy API collegando un criterio Aggiungi CORS al proxy API volgendo i seguenti passaggi:
- Quando crei il criterio selezionando la casella di controllo Aggiungi intestazioni CORS nella pagina Sicurezza della procedura guidata Crea un proxy
- Aggiungendolo in un secondo momento dalla finestra di dialogo Aggiungi norme
Quando aggiungi il criterio CORS selezionando la casella di controllo, un criterio denominato Aggiungi CORS viene aggiunto automaticamente al sistema e allegato al preflight della richiesta TargetEndpoint.
Il criterio Aggiungi CORS aggiunge le intestazioni appropriate alla risposta. In sostanza, le intestazioni consentono al browser di sapere con quali origini condividerà le risorse, quali metodi accetta e così via. Puoi scoprire di più su queste intestazioni CORS nel Recommendation W3C sulla condivisione delle risorse tra origini.
Devi modificare il criterio come segue:
- Aggiungi le intestazioni
content-type
eauthorization
(obbligatorie per supportare l'autenticazione di base o OAuth2) all'intestazioneAccess-Control-Allow-Headers
, come mostrato nell'estratto di codice di seguito. - Per l'autenticazione OAuth2, potrebbe essere necessario adottare misure per correggere un comportamento non conforme allo standard RFC.
<CORS continueOnError="false" enabled="true" name="add-cors"> <DisplayName>Add CORS</DisplayName> <AllowOrigins>{request.header.origin}</AllowOrigins> <AllowMethods>GET, PUT, POST, DELETE</AllowMethods> <AllowHeaders>origin, x-requested-with, accept, content-type, authorization</AllowHeaders> <ExposeHeaders>*</ExposeHeaders> <MaxAge>3628800</MaxAge> <AllowCredentials>false</AllowCredentials> <GeneratePreflightResponse>true</GeneratePreflightResponse> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> </CORS>
Aggiunta di intestazioni CORS a un proxy esistente
Nuovo editor proxy
Per aggiungere il criterio CORS a un proxy API esistente:
Se utilizzi l'interfaccia utente di Apigee nella console Cloud: seleziona Sviluppo proxy > Proxy API.
Se utilizzi la UI di Apigee classica: seleziona Sviluppa > Proxy API e nel riquadro Proxy, seleziona l'ambiente per il proxy.
- Seleziona il proxy API a cui vuoi aggiungere il criterio CORS.
- Nell'editor del nuovo proxy API, fai clic sulla scheda Sviluppa.
- Nel riquadro a sinistra, fai clic sul pulsante + nella riga Criteri.
Nella finestra di dialogo Crea criterio, fai clic nel campo Seleziona il tipo di criterio, scorri verso il basso fino a Sicurezza e seleziona CORS.
Inserisci i dettagli del criterio e fai clic su Crea.
- Nel riquadro a sinistra, fai clic su PreFlow in Endpoint di destinazione > predefinito.
- Fai clic sul pulsante + accanto a PreFlow nel riquadro Richiesta in basso a destra nell'editor visivo.
- Nella finestra di dialogo Passaggio Aggiungi criteri, seleziona il criterio CORS.
Fai clic su Aggiungi per allegare il criterio.
Editor proxy classico
Per aggiungere il criterio CORS a un proxy API esistente:
- Accedi all'interfaccia utente di Apigee.
- Seleziona Sviluppa > Proxy API nella barra di navigazione a sinistra. Se vedi il pulsante Prova ora, fai clic per visualizzare la nuova visualizzazione Sviluppa.
- Seleziona il proxy API a cui vuoi aggiungere il criterio CORS.
- Nell'editor del nuovo proxy API, fai clic sulla scheda Sviluppa:
- Nel riquadro Navigator a sinistra, fai clic su PreFlow in Endpoint di destinazione > predefinito.
- Fai clic sul pulsante +Passaggio in alto, corrispondente al PreFlow della richiesta. Viene visualizzato
un elenco classificato di tutti i criteri che puoi creare.
- Seleziona CORS nella categoria Sicurezza.
- Fornisci un nome, ad esempio
Add CORS
, quindi fai clic su Aggiungi.
La visualizzazione Sviluppa è mostrata di seguito.
Gestione delle richieste preflight CORS
Per preflight CORS si intende l'invio di una richiesta a un server per verificare se supporta CORS. Le risposte preflight tipiche includono le origini da cui il server accetterà le richieste CORS, un elenco di metodi HTTP supportati per le richieste CORS, le intestazioni che possono essere utilizzate nell'ambito della richiesta di risorse, il tempo massimo di memorizzazione nella cache della risposta preflight e altro ancora. Se il servizio non indica il supporto di CORS o non vuole accettare richieste cross-origin dall'origine del client, verrà applicato il criterio cross-origin del browser e tutte le richieste cross-domain effettuate dal client per interagire con le risorse ospitate su quel server non andranno a buon fine.
In genere, le richieste preflight CORS vengono effettuate con il metodo HTTP OPTIONS. Quando un server che supporta CORS riceve una richiesta OPTIONS, restituisce al client un insieme di intestazioni CORS che indicano il suo livello di supporto CORS. In seguito a questo handshake, il client sa cosa è autorizzato a richiedere dal dominio non di origine.
Per ulteriori informazioni sul preflight, consulta la Recommendation del W3C sulla condivisione delle risorse tra origini. Esistono inoltre numerosi blog e articoli sul CORS a cui puoi fare riferimento.
Apigee non include una soluzione di preflight CORS pronta all'uso, ma è possibile implementarla, come descritto in questa sezione. L'obiettivo è che il proxy valuti una richiesta OPTIONS in un flusso condizionale. Il proxy può quindi inviare una risposta appropriata al client.
Diamo un'occhiata a un flusso di esempio e poi discutiamo le parti che gestiscono la richiesta di preflight:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ProxyEndpoint name="default"> <Description/> <Flows> <Flow name="OptionsPreFlight"> <Request> <Step> <Name>add-cors</Name> </Step> </Request> <Response/> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </Flow> </Flows> <PreFlow name="PreFlow"> <Request/> <Response/> </PreFlow> <HTTPProxyConnection> <BasePath>/v1/cnc</BasePath> <VirtualHost>default</VirtualHost> <VirtualHost>secure</VirtualHost> </HTTPProxyConnection> <RouteRule name="NoRoute"> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </RouteRule> <RouteRule name="default"> <TargetEndpoint>default</TargetEndpoint> </RouteRule> <PostFlow name="PostFlow"> <Request/> <Response/> </PostFlow> </ProxyEndpoint>
Le parti chiave di questo ProxyEndpoint sono le seguenti:
- Viene creata una regola di routing per un target NULL con una condizione per la richiesta OPTIONS. Tieni presente che
non è specificato TargetEndpoint. Se la richiesta OPTIONS viene ricevuta e le intestazioni delle richieste Origin e Access-Control-Request-Method non sono nulle, il proxy restituisce immediatamente le intestazioni CORS in una risposta al client (bypassando l'obiettivo "backend" predefinito effettivo).
Per informazioni dettagliate sulle condizioni di flusso e su RouteRule, consulta la sezione Condizioni con variabili di flusso.
<RouteRule name="NoRoute"> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </RouteRule>
- Viene creato un flusso OptionsPreFlight che aggiunge al flusso un criterio Aggiungi CORS contenente le intestazioni CORS se viene ricevuta una richiesta OPTIONS e le intestazioni delle richieste Origin e Access-Control-Request-Method non sono nulle.
<Flow name="OptionsPreFlight"> <Request> <Step> <Name>add-cors</Name> </Step> </Request> <Response/> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </Flow>