2016-04-16 23 views
6

Sto effettuando una query a un servizio Web utilizzando jQuery AJAX. La mia domanda è simile al seguente:jQuery La chiamata AJAX risulta in stato di errore 403

var serviceEndpoint = 'http://example.com/object/details?version=1.1'; 
$.ajax({ 
    type: 'GET', 
    url: serviceEndpoint, 
    dataType: 'jsonp', 
    contentType: 'jsonp', 
    headers: { 'api-key':'myKey' }, 
    success: onSuccess, 
    error: onFailure 
}); 

Quando eseguo questo, ottengo un errore di stato di 403. Non capisco il motivo per cui i miei risultati di chiamata ad avere il codice di stato 403. Sono nel controllo della sicurezza sul il mio servizio ed è contrassegnato come spalancato. So che la chiave è valida, perché la sto usando in un'altra chiamata, che funziona. Ecco la chiamata che funziona:

var endpoint = 'http://example.com/object/data/item?version=1.1'; 
$.ajax({ 
    type: 'POST', 
    url: endpoint, 
    cache: 'false', 
    contentType:'application/json', 
    headers: { 
    'api-key':'myKey', 
    'Content-Type':'application/json' 
    }, 
    data: JSON.stringify({ 
    id: 5, 
    count:true 
    }), 
    success: onDataSuccess, 
    error: onDataFailure 
}); 

So che si tratta di due endpoint diversi. Ma sono convinto al 100% che non si tratta di un'autenticazione lato server o di un errore di autorizzazione. Ancora una volta, tutto è completamente aperto sul lato server. Il che implica che sto facendo un errore sulla mia richiesta lato client.

Sento che dovrei comunicare che questa richiesta viene fatta durante lo sviluppo. Quindi, sto eseguendo questo da http://localhost:3000. Per questo motivo, ho immediatamente pensato che si trattasse di un problema CORS. Ma tutto sembra corretto. Il fatto che la mia richiesta POST funzioni, ma il mio GET non mi ha assolutamente frustrato. Mi sto perdendo qualcosa? Cosa potrebbe essere?

+2

Hai provato a aprire l'URL direttamente nel tuo browser? Ti manca la parte '/ data /' dell'URL per abbinare quella che funziona? – charlietfl

+1

Si noti che non è possibile inviare intestazioni per la richiesta 'jsonp', si tratta di una richiesta di script. Sei sicuro di volere 'jsonp' e non' json'? Anche perché 'JSON.stringify()' per le intestazioni? GET non ha richieste 'contentType'. dal momento che non viene inviato alcun contenuto corporeo. Hai numerosi problemi ognuno dei quali può essere un problema – charlietfl

+0

@charlietfl Ho provato ad aprire nel browser. Non ho familiarità con nessuna parte di '/ data /' che devo includere. Ho letteralmente bisogno di passare in 'version' e' api-key'. Supponevo che avrei dovuto inserire 'API-key' come intestazione. Devo impostare le proprietà 'data' e' contentType' su 'jsonp'? Sembra che dovrebbe essere una semplice chiamata. Ma chiaramente, sto sbucciando e trascurando qualcosa. Come dovrebbe apparire la chiamata corretta? –

risposta

12

Il motivo dell'errore 403 è non si inviano intestazioni. Poiché stai effettuando una richiesta CORS, non puoi inviare intestazioni personalizzate a meno che il server non abiliti questa intestazione aggiungendo Access-Control-Allow-Headers alla risposta.

In un preflighted-request, il client effettua 2 richieste al server. Il primo è preflight (con metodo OPTION) e il secondo è la vera richiesta. Il server invia l'intestazione Access-Control-Allow-Headers come risposta della richiesta di preflight. Quindi abilita alcune intestazioni da inviare. In questo modo la tua richiesta POST può funzionare, perché la richiesta POST è una richiesta preflight. Ma per una richiesta GET, non c'è preflight per raccogliere l'intestazione Access-Control-Allow-Headers. Quindi il browser non invia le intestazioni personalizzate.

Una soluzione per questo problema:

Per aggirare il problema, impostare il vostro dataType e contentType al json come il seguente:

var serviceEndpoint = 'http://example.com/object/details?version=1.1'; 
$.ajax({ 
    type: 'GET', 
    url: serviceEndpoint, 
    dataType: 'json', 
    contentType: 'json', 
    headers: { 'api-key':'myKey' }, 
    success: onSuccess, 
    error: onFailure 
}); 

In questo modo, la tua richiesta GET sarà un preflighted request. Se il tuo server abilita l'intestazione Access-Control-Allow-Headers con l'api-key, funzionerà.

configurazione del server di esempio per la richiesta di cui sopra (scritto in express.js):

res.setHeader('Access-Control-Allow-Origin', '*'); 
res.setHeader('Access-Control-Allow-Methods', '*'); 
res.setHeader('Access-Control-Allow-Headers', 'api-key,content-type'); 
res.setHeader('Access-Control-Allow-Credentials', true); 

aggiunto:

In realtà, contentType dovrebbe essere sia application/javascript o application/json mentre si fa una richiesta jsonp. Non c'è contentType come jsonp.

+0

dove dovrebbe il codice res.setHeader deve essere scritto? Inoltre, che tipo di oggetto è res? – Zoran777

+0

@ Zoran777 sarà sul lato server. [ecco i documenti] (http://expressjs.com/en/api.html#app.get.method) per 'res' nel server' express'. – ykaragol

0

Se si guarda alla API page per chiamata Ajax di jQuery, si menziona il seguente nella sezione Content-Type:

Nota: Per richieste tra domini, impostare il tipo di contenuto a qualsiasi cosa altri di application/x-www-form-urlencoded, multipart/form-data, o text/plain attiverà il browser per inviare una richiesta OPZIONI di preflight al server.

Quella pagina in realtà non parlare di quello che una "richiesta di opzioni di preflight" è, ma ho trovato alcuni link interessanti quando si cerca quella frase su on-line:

L'interessante è lo code example & il CORS image nella pagina HTML5Rocks. L'immagine mostra come vengono effettuate le chiamate Ajax dal codice JavaScript al browser al server & come le risposte sono round-trip tra tutte e 3 di queste.

Tendiamo a pensare a JavaScript + Browser = Client, ma nell'illustrazione l'autore sta spiegando la differenza tra il codice dello sviluppatore web & il codice dello sviluppatore del browser, dove il primo è scritto nel codice JavaScript, ma quest'ultimo è stato scritto usando il codice C, C++ o C#.

Un buon strumento di analisi dei pacchetti è Fiddler, che sarebbe simile a Wireshark. Uno di questi strumenti dovrebbe mostrarti le richieste di pre-volo che vengono inviate dal browser al server. Molto probabilmente, è qui che la richiesta Ajax viene bloccata dal server con uno 403 Forbidden error.

Problemi correlati