2012-02-01 2 views
28

Orso con me, questo ha bisogno di un po 'di spiegazione.Credenziali cookie CORS da WebView mobile caricate localmente con file: //

Sto collaborando alla creazione di un'app mobile web ibrida. 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 iniziale initSession(), è necessario inviare il cookie JSESSIONID con ogni richiesta (AJAX).

Quando distribuito su un dispositivo mobile, l'app Web viene avvolta nella visualizzazione Web nativa, che avvia l'applicazione Web sfogliando file:///path/to/app/index.html.

La prima cosa che abbiamo provato è stata chiedere al nostro cliente di impostare Access-Control-Allow-Origin: * nell'intestazione della risposta per consentire CORS. Abbiamo poi provato inviare al server:

$.ajax({ 
    url: 'http://thirdparty.com/ws', 
    data: data, 
    type: "POST", 
    dataType: "JSON", 
    success: successCallback, 
    error: failedCallback 
}); 

monitoraggio delle richieste, era evidente che i biscotti non erano stati inclusi. Ad un'ispezione più ravvicinata c'è un special section in the CORS spec for dealing with user credentials, 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 il seguente:

Se il server di terze parti non ha risposto con un colpo di testa Access-Control-Allow-Credentials: true la risposta sarebbe stata ignorata e non messi a disposizione di contenuti 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 jolly.

così abbiamo bisogno di cambiare le intestazioni del server per includere Access-Control-Allow-Credentials: true e Access-Control-Allow-Origin alla nostra origine.

Eccoci finalmente al mio problema: when loading a web page using the file:// protocol, l'intestazione della richiesta Origin inviata da Web View è 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 è in grado di impostare Access-Control-Allow-Origin su un valore diverso da *, non è possibile inviare credenziali, inclusi i cookie.

Quindi sono bloccato. Cosa fare? I saw a similar question posted here ma non capisco davvero la risposta proposta. Qualsiasi aiuto sarebbe molto apprezzato!

+2

L'unica soluzione mi viene in mente potrebbe essere quella di utilizzare un server per colpire il servizio web. Puoi scrivere un gestore HTTP e cliccarlo dalla tua app mobile. Ovviamente questo aggiunge un overhead aggiuntivo nella manutenzione del server, ma devi avere qualcosa a disposizione, no? –

+0

Sì, questa è la soluzione provvisoria, un brutto gateway intermedio php phet. Non è davvero l'ideale, ma almeno funziona per il momento. – fiznool

+0

Una cosa che potrei fare è chiedere agli sviluppatori di phonegap se hanno già visto qualcosa di simile prima e avere qualche soluzione ... – fiznool

risposta

0

Prova a guardare 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.

+0

Grazie per le informazioni. Idealmente non sto cercando un cambiamento radicale nel modo in cui sviluppiamo le app, ma vedrò cosa ci può offrire 5app. – fiznool

0

richiesta Usa JSONP. La richiesta JSONP ti consente di effettuare una richiesta di dominio incrociato. Here è un esempio.

+0

'JSONP' funzionerà solo con richieste' GET'. –

7

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() utilizzato, una richiesta OPTIONS viene inviata al server.

Ciò preflight OPTIONS richiesta è effettivamente facendo sta dicendo:

"Ehi là, straniero-server-da-qualche-altro-dominio, voglio inviare una richiesta di non-semplici (semplici REQ di non sono preflight). La mia richiesta non semplice avrà questo tipo di intestazioni e tipo di contenuto e così via. Puoi farmi sapere se va bene? "

Quindi il server farà tutto quello che fa (probabilmente verificare alcune configurazioni o database) e rispondere con l'origine ammissibile (s), l'intestazione ammissibile (s), e/o il metodo ammissibile (s).

Infine, se la richiesta di preflight OPTIONS ha ricevuto risposta che consente l'effettivo metodo $.ajax(), va.

CORS non è uguale a JSONP.

Detto - mentre withCredentials successo preflight richiede la risposta di portare un'intestazione Access-Control-Allow-Credentials (come indicato in questione), che si aggiunge a Access-Control-Allow-Origins E Access-Control-Allow-Methods valori, che devono comprendere le sfaccettature della richiesta prevista.

Per esempio - se si stanno facendo un POST richiesta CORS di origine http://foo-domain.com con intestazioni somevalue a http://bar-domain.com, un OPTIONS richiesta di verifica preliminare sarebbe uscire e in modo che la richiesta di post vero e proprio da apportare al http://bar-domain.com, la richiesta OPTIONS avrebbe bisogno per ricevere una risposta con un valore Access-Control-Allow-Origins incluso 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 sia consentita l'intestazione somevalue, la risposta deve contenere un valore Access-Control-Allow-Headers che includa la nostra chiave di intestazione somevalue o *.

Per tornare indietro: se non è possibile controllare il server o non è possibile consentire al server di consentire le richieste CORS, è sempre possibile utilizzare JSONP o alcuni tipi di dati urlEncoded e/o effettuare semplici richieste senza intestazioni personalizzate. GET, HEAD e le richieste complete POST sono in genere semplici richieste.

+2

Nota a margine: quando si risponde a una richiesta con credenziali, il server deve specificare un dominio e non può utilizzare la wild card ('*'). –

1

Il mio suggerimento è impostato per ACCESS-CONTROL-ALLOW-ORIGINnull sul lato server

Sì, questa domanda mi dà fastidio per un po '.

Riguardo al CORS spec, null in grado di soddisfare la situazione in cui una richiesta CORS da un file:// schema

E una raccomandazione pratico su quella specifica è per impostarla come origin-list-or-null, ovvero un elenco di origini di spazi separati o semplicemente "null" (a proposito, la stringa %x6E %x75 %x6C %x6C dalla definizione per origin-list-or-null è letteralmente null HEX-codificato)

Infine si chiederà, suole che pari a * se impostiamo ACCESS-CONTROL-ALLOW-ORIGIN-null poiché ogni richiesta dallo schema file:// è valida (il che significa che ogni app ibrida può accedere all'endpoint se conosce la tua uri)?

Bene, dato Access-Control-Allow-Credentials: true, credo che tu abbia un intero meccanismo di autenticazione che funziona sul server. Avrebbe dovuto filtrato quelle richieste senza l'autenticazione corretta

auguriamo che contribuiscano