Abbi pazienza, questo ha bisogno di un po ‘di spiegazioni.
Sto collaborando alla creazione di un’app ibrida per Web mobile. Il codebase principale è HTML5 e JavaScript, che verrà inserito in una visualizzazione Web mobile nativa (a la Phonegap).
Parte della funzionalità richiede che l’app invii informazioni a un servizio web controllato da uno dei nostri clienti. C’è molto poco spazio per cambiare questo servizio web in quanto viene utilizzato da altri. Inviamo JSON utilizzando un POST HTTP e riceviamo le risposte dal server. Parte di questa risposta è un cookie JSESSIONID che gestisce la nostra sessione con il server. Dopo la chiamata initSession()
iniziale, è necessario inviare il cookie JSESSIONID con ogni richiesta (AJAX).
Quando viene distribuito su un dispositivo mobile, l’app Web viene avvolta nella visualizzazione Web nativa, che avvia l’applicazione Web sfogliando il file:///path/to/app/index.html
.
La prima cosa che abbiamo provato è stata chiedere al nostro client di impostare Access-Control-Allow-Origin: *
nell’intestazione della risposta per consentire a CORS. Abbiamo quindi provato a postare sul server:
$.ajax({ url: 'http://thirdparty.com/ws', data: data, type: "POST", dataType: "JSON", success: successCallback, error: failedCallback });
Monitorando le richieste, era evidente che i cookie non venivano inclusi. Ad un’ispezione più ravvicinata c’è una sezione speciale nelle specifiche CORS per trattare le credenziali dell’utente , che include i cookie di sessione. Così ho modificato la chiamata AJAX per includere questo:
$.ajax({ url: 'http://thirdparty.com/ws', data: data, type: "POST", dataType: "JSON", success: successCallback, error: failedCallback, xhrFields { withCredentials: true } });
Un altro errore, questa volta dal browser. Più lettura ha prodotto quanto segue:
Se il server di terze parti non ha risposto con un
Access-Control-Allow-Credentials: true
header la risposta verrebbe ignorata e non resa disponibile per il contenuto web.Nota importante: quando si risponde a una richiesta con credenziali, il server deve specificare un dominio nell’intestazione
Access-Control-Allow-Origin
e non può utilizzare la wild card.
Quindi abbiamo bisogno di cambiare le intestazioni del server per includere Access-Control-Allow-Credentials: true
e Access-Control-Allow-Origin
per la nostra origine.
Ecco finalmente il mio problema: quando si carica una pagina Web utilizzando il protocollo file: // , l’intestazione della richiesta Origin
inviata dalla vista Web è impostata su null
. Pertanto non può essere analizzato dal server e quindi il server non può impostarlo in Access-Control-Allow-Origin
. Ma se il server non può impostare Access-Control-Allow-Origin
su un valore diverso da *
non possiamo inviare credenziali, inclusi i cookie.
Quindi sono bloccato. Cosa fare? Ho visto una domanda simile pubblicata qui, ma non capisco davvero la risposta proposta. Qualsiasi aiuto sarebbe molto apprezzato!
Mi rendo conto che questa domanda è vecchia, ma ho pensato di buttarcela comunque. Nel caso di richieste CORS, il browser li prefligherà. Ciò significa che, nonostante il metodo $.ajax()
che si sta utilizzando, una richiesta OPTIONS
viene inviata al server.
Ciò che questa richiesta OPTIONS
preflight sta effettivamente facendo è dire:
“Ehilà, foreign-server-from-some-other-domain, voglio inviarti una richiesta non semplice (i req semplici non sono preflight). La mia richiesta non-semplice prevede di avere questo tipo di intestazioni e tipo di contenuto e così via. Puoi dirmi se va bene? ”
Quindi il server farà tutto ciò che fa (probabilmente controlla qualche configurazione o database) e risponderà con l’origine (i) consentita (i), l’intestazione (i) ammissibile (i) e / oi metodi consentiti (s).
Infine, se la richiesta OPTIONS
preflight ha ricevuto una risposta che consente l’effettivo metodo $.ajax()
, va.
CORS non è lo stesso di JSONP.
Detto ciò, mentre withCredentials
il successo preflight di withCredentials
necessario che la risposta withCredentials
Access-Control-Allow-Credentials
(come indicato nella domanda), ovvero IN AGGIUNTA a Access-Control-Allow-Origins
AND Access-Control-Allow-Methods
valori, che devono includere gli aspetti della richiesta desiderata.
Per esempio – se stai facendo una richiesta CORS POST
dall’origine http://foo-domain.com
con intestazioni somevalue
a http://bar-domain.com
, una richiesta OPTIONS
preflight uscirà e in ordine per il post effettivo richiesta per essere effettuata su http://bar-domain.com
, la richiesta OPTIONS
dovrebbe ricevere una risposta con un valore Access-Control-Allow-Origins
che includesse http://foo-domain.com
. Questo potrebbe essere il nome di origine stesso o *
. La risposta dovrebbe anche avere un valore Access-Control-Allow-Methods
che includa POST
. Questo potrebbe anche essere *
. Infine, se vogliamo che la nostra intestazione di somevalue
sia consentita, la risposta deve contenere un valore Access-Control-Allow-Headers
che includa la nostra chiave di intestazione di somevalue
o *
.
Per tornare indietro: se non riesci a controllare il server o non hai modo di consentire al server di consentire le tue richieste CORS, puoi sempre utilizzare JSONP o alcuni tipi di dati urlEncoded e / o effettuare semplici richieste senza intestazioni personalizzate. GET
, HEAD
e POST
richieste POST
complete sono in genere richieste semplici.
Immagino che se stai creando un’applicazione ibrida stai usando cordova. Se questo è il caso in cui non hai bisogno di CORS hai solo bisogno di elencare in bianco i domini a cui accederai.
http://docs.phonegap.com/en/3.0.0/guide_appdev_whitelist_index.md.html
Il mio suggerimento è impostare ACCESS-CONTROL-ALLOW-ORIGIN
su null
sul lato server
Sì, questa domanda mi disturba un po ‘.
Per quanto riguarda le specifiche CORS , null
può soddisfare la situazione in cui una richiesta CORS da un file://
schema
E una raccomandazione pratica su quella specifica è impostarla come origine-lista-o-nulla , che è o una lista di origini separate dallo spazio o semplicemente “null” (a proposito, la stringa %x6E %x75 %x6C %x6C
dalla definizione per origin-list-or-null
è letteralmente null
esadecimale)
Infine chiederai, non sarà uguale a *
se impostiamo ACCESS-CONTROL-ALLOW-ORIGIN
su null
poiché ogni richiesta dal file://
schema file://
è valida (il che significa che ogni app ibrida può accedere al tuo endpoint se sa del tuo uri) ?
Bene, dato Access-Control-Allow-Credentials: true
, credo che tu abbia un intero meccanismo di autenticazione che funziona sul server. Dovrebbe aver filtrato quelle richieste senza l’autenticazione corretta
Spero che ti sarà d’aiuto
Prova a guardare http://www.5app.co.uk. Evita l’uso delle chiamate XHR e funziona in modo affidabile sui dispositivi mobili quando le connessioni dati vanno e vengono. Il gateway quindi si interfaccia con il cliente.
Usa la richiesta JSONP. La richiesta JSONP ti consente di effettuare una richiesta di dominio incrociato. Ecco un esempio.
Ad esempio, sul lato php è necessario impostare questo:
header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization, X-Request-With, Set-Cookie, Cookie, Bearer'); header('Access-Control-Allow-Credentials: true'); // header('Cookie: PHPSESSID='.$_COOKIE['PHPSESSID']);