2016-04-16 10 views
6

Ich mache eine Abfrage an einen Webdienst mit jQuery AJAX. Meine Abfrage sieht wie folgt aus:jQuery AJAX-Aufruf führt zu Fehlerstatus 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 
}); 

Als ich dies ausführen, erhalte ich einen Statusfehler von 403. Ich verstehe nicht, warum mein Anruf ergibt, die den Statuscode 403. ich die Kontrolle über die Sicherheit bin auf mein Service und es ist als weit offen markiert. Ich weiß, dass der Schlüssel gültig ist, weil ich ihn in einem anderen Anruf verwende, der funktioniert. Hier ist der Anruf, der funktioniert:

Ich weiß, das sind zwei verschiedene Endpunkte. Aber ich bin zu 100% überzeugt, dass dies kein serverseitiger Authentifizierungs- oder Berechtigungsfehler ist. Wieder ist alles serverseitig offen. Was bedeutet, dass ich auf meiner Client-Seite einen Fehler mache.

Ich glaube, ich sollte mitteilen, dass diese Anforderung während der Entwicklung gestellt wird. Also, ich führe das von http://localhost:3000. Aus diesem Grund habe ich sofort angenommen, dass es sich um ein CORS-Problem handelt. Aber alles sieht korrekt aus. Die Tatsache, dass meine POST-Anfrage funktioniert, aber mein GET hat mich nicht absolut frustriert. Fehle ich etwas? Was könnte es sein?

+2

Haben Sie sogar versucht, diese URL direkt in Ihrem Browser zu öffnen? Vermissen Sie den '/ data /' Teil der URL, um mit dem zu funktionieren, der funktioniert? – charlietfl

+1

Beachten Sie, dass Sie keine Header für 'jsonp' Anfrage senden können, es ist eine Skriptanfrage. Bist du sicher, dass du 'jsonp' und nicht' json' willst? Auch warum 'JSON.stringify()' für Header? GET hat keine Anfrage 'contentType'. da kein Körperinhalt gesendet wird. Sie haben zahlreiche Probleme, von denen jedes Problem sein kann – charlietfl

+0

@charlietfl Ich habe versucht, im Browser zu öffnen. Ich kenne keinen '/ data /' -Teil, den ich einbeziehen muss. Ich muss nur die "Version" und den "API-Schlüssel" eingeben. Ich nahm an, dass ich den 'api-Schlüssel' als Kopfzeile verwenden sollte. Muss ich die Eigenschaften 'data' und' contentType' auf 'jsonp' setzen? Dies scheint ein einfacher Anruf zu sein. Aber klar, ich vermassle es und übersehe etwas. Wie sollte der richtige Anruf aussehen? –

Antwort

12

Der Grund für 403 Fehler ist Sie senden keine Header. Da Sie eine CORS-Anfrage stellen, können Sie keine benutzerdefinierten Header senden, es sei denn, der Server aktiviert diese Header, indem Sie der Antwort Access-Control-Allow-Headers hinzufügen.

In einem preflighted-request stellt Client 2 Anforderungen an den Server. Die erste ist Preflight (mit OPTION-Methode) und die zweite ist die echte Anfrage. Der Server sendet den Header Access-Control-Allow-Headers als Antwort auf die Preflight-Anforderung. So können einige Header gesendet werden. Auf diese Weise kann Ihre POST-Anfrage funktionieren, da die POST-Anfrage eine Preflight-Anfrage ist. Aber für eine GET-Anfrage gibt es kein Preflight zum Sammeln von Access-Control-Allow-Headers Header. Der Browser sendet also keine benutzerdefinierten Header.

Eine Abhilfe für dieses Problem:

Als Abhilfe können, geben Sie Ihre dataType und contentType zu json wie die folgenden:

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 
}); 

Auf diese Weise können, um Ihre Anfrage ein preflighted request sein wird. Wenn Ihr Server die mit Access-Control-Allow-Headers Header aktiviert, wird es funktionieren.

Beispiel-Serverkonfiguration für die obige Anfrage (in Express.js geschrieben):

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); 

ZUSäTZLICH:

Eigentlich contentType sollte entweder application/javascript oder application/json sein, während eine JSONP Anfrage zu tun. Es gibt keine contentType als jsonp.

+0

wo sollte die res.setHeader Code geschrieben werden? Welche Art von Objekt ist res? – Zoran777

+0

@ Zoran777 wird es auf der Serverseite sein. [hier ist die Dokumentation] (http://expressjs.com/en/api.html#app.get.method) für 'res' in' express' Server. – ykaragol

0

Wenn man sich die API page für jQuery Aufruf Ajax aussehen, erwähnt sie die folgenden in der Content-Type Abschnitt:

Hinweis: Für Cross-Domain-Anfragen, den Inhaltstyp auf etwas einstellen andere als application/x-www-form-urlencoded, multipart/form-data oder text/plain löst den Browser aus, um eine Preflight OPTIONS Anfrage an den Server zu senden.

Diese Seite nicht wirklich erwähnen, was eine "Preflight-OPTIONS-Anforderung" ist, aber ich fand einige interessante Links, wenn diese Phrase Online aufzublicken:

Was ist interessant ist die code example & die CORS image auf der HTML5Rocks Seite. Das Bild zeigt, wie die Ajax-Aufrufe vom JavaScript-Code zum Browser zum Server & gemacht werden, wie die Antworten zwischen allen 3 Runden round-tripping sind.

Wir neigen dazu, an JavaScript + Browser = Client zu denken, aber in der Abbildung erklärt der Autor den Unterschied zwischen dem Code des Webentwicklers & des Browserentwicklercodes, wobei ersteres in JavaScript-Code geschrieben ist, aber letzteres geschrieben wurde Verwenden von C, C++ oder C# -Code.

Ein gutes Paketanalyse-Tool ist Fiddler, das Wireshark ähnlich wäre. Eines dieser Tools sollte Ihnen die Pre-Flight-Anforderungen anzeigen, die vom Browser an den Server gesendet werden. Höchstwahrscheinlich wird Ihre Ajax-Anfrage vom Server mit einer 403 Forbidden error blockiert.