2016-04-16 77 views
6

我正在使用jQuery AJAX查詢Web服務。我的查詢是這樣的:jQuery AJAX調用導致錯誤狀態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 
}); 

當我執行,我得到的403狀態錯誤,我不明白爲什麼在具有狀態碼403我的通話效果我在安全的控制是在我的服務和它被標記爲廣泛開放。我知道密鑰是有效的,因爲我在另一個調用中使用它,這是有效的。以下是可用的呼叫:

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

我知道這些是兩個不同的終結點。但我100%確信這不是服務器端身份驗證或權限錯誤。再一次,服務器端的所有東西都是開放的。這意味着我在我的客戶端請求上犯了一些錯誤。

我覺得我應該傳達這個請求是在開發過程中進行的。所以,我從http://localhost:3000運行此。出於這個原因,我立即認爲這是一個CORS問題。但一切看起來都正確。我的POST請求起作用的事實,但我的GET並沒有讓我絕對沮喪。我錯過了什麼嗎?會是什麼呢?

+2

你甚至嘗試直接在瀏覽器中打開該網址嗎?你是否遺漏了URL的'/ data /'部分以匹配工作的部分? – charlietfl

+1

請注意,您無法爲'jsonp'請求發送標頭,這是一個腳本請求。你確定要'jsonp'而不是'json'嗎?另外爲什麼'JSON.stringify()'頭文件? GET沒有請求'contentType'。因爲沒有正文內容被髮送。你有許多問題中的任何一個都可能是問題 – charlietfl

+0

@charlietfl我曾嘗試在瀏覽器中打開。我不熟悉我需要包含的任何'/ data /'部分。我只是需要傳入'version'和'api-key'。我認爲我應該把'api-key'作爲頭文件。我是否需要將'data'和'contentType'屬性設置爲'jsonp'?這似乎應該是一個簡單的電話。但顯然,我正在修補它並忽略了一些東西。正確的電話應該是什麼樣子? –

回答

12

403錯誤的原因是你不發送標題。由於您正在發出CORS請求,因此您無法發送任何自定義標題,除非服務器通過將Access-Control-Allow-Headers添加到響應中來啓用這些標題。

preflighted-request中,客戶端向服務器發出2個請求。第一個是預檢(使用OPTION方法),第二個是真正的請求。服務器發送Access-Control-Allow-Headers標題作爲預檢請求的響應。所以它能夠發送一些頭文件。通過這種方式,您的POST請求可以工作,因爲POST請求是預檢請求。但是對於GET請求,沒有任何預檢來收集Access-Control-Allow-Headers標題。所以瀏覽器不會發送您的自定義標題。

針對此問題的解決方法:

作爲一種變通方法,將您的dataTypecontentTypejson爲以下幾點:

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

通過這種方式,您的GET請求將是一個preflighted request。如果您的服務器啓用api-keyAccess-Control-Allow-Headers標題,它將起作用。

用於上述請求(寫在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); 

ADDED:

實際上,contentType應爲application/javascriptapplication/json而做JSONP請求。沒有contentType作爲jsonp

+0

哪裏應該res.setHeader代碼被寫入?另外,什麼樣的對象是res? – Zoran777

+0

@ Zoran777它將在服務器端。 [這裏是文檔](http://expressjs.com/en/api.html#app.get.method)用於'express'服務器中的'res'。 – ykaragol

0

如果你看一下API page的jQuery的Ajax調用,它提到在Content-Type部分如下:

注:對於跨域請求,內容類型設置爲任何 其他比應用程序/ x-www-form-urlencoded,multipart/form-data或 text/plain將觸發瀏覽器向服務器發送預檢選項 請求。

該網頁並沒有真正提什麼「預檢OPTIONS請求」是的,但我發現了一些有趣的環節看,當這句話在線:

什麼是intersting是在HTML5Rocks頁面code example & CORS image。該圖像顯示瞭如何將Ajax調用從JavaScript代碼發送到服務器到服務器&這些響應如何在所有這三者之間進行往返。

我們傾向於想到JavaScript + Browser = Client,但在圖中,作者正在解釋Web開發人員的代碼&之間的差異,瀏覽器開發人員的代碼中前者用JavaScript代碼編寫,後者則編寫使用C,C++或C#代碼。

一個很好的數據包分析工具是Fiddler,它將類似於Wireshark。這些工具中的任何一種都應該向您顯示從瀏覽器發送到服務器的預發送請求。很可能,這是您的Ajax請求遭到服務器阻止的情況,其中403 Forbidden error

相關問題