2015-09-10 44 views
113

我遇到過多次CORS問題,通常可以解決它,但我想通過從MEAN堆棧範例中看到這一點來真正理解它。請求標頭字段Access-Control-Allow-Headers在預檢響應中本身是不允許的

在我簡單地在我的快速服務器中添加中間件來捕獲這些內容之前,它看起來像是某種預鉤使我的請求錯誤。

Request header field Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers in preflight response

我認爲我能做到這一點:

app.use(function(req, res, next) { 
    res.header("Access-Control-Allow-Headers","*") 
}) 

或等值但這似乎並沒有解決它。我當然也試過

app.use(function(req, res, next) { 
    res.header("Access-Control-Allow-Headers","Access-Control-Allow-Headers") 
}) 

還是沒有運氣。

回答

114

當您開始使用自定義請求標頭時,您將獲得CORS預檢。這是一個請求,它使用HTTP OPTIONS動詞幷包含若干標題,其中一個是Access-Control-Request-Headers,列出了客戶端希望包含在請求中的標題。

您需要使用相應的CORS標題回覆該CORS預檢才能使其工作。其中之一的確是Access-Control-Allow-Headers。該標題需要包含Access-Control-Request-Headers標題包含的相同值(或更多)。

https://fetch.spec.whatwg.org/#http-cors-protocol更詳細地解釋了此設置。

+15

如果您使用Chrome,並且您不知道被請求的是什麼頭,使用開發者控制檯,網絡選擇正在進行的呼叫,您可以查看'訪問控制請求,Headers'被請求的是什麼頭 –

+2

Developer Console選項是一個不錯的選擇。您還可以通過訪問服務器上的請求對象並轉儲報頭的值,但特別是「Access-Control-Request-Headers」的報頭值來找到所需的內容。然後,複製/粘貼到您的response.setHeader(「Access-Control-Allow-Headers」,「{paste here}」) –

+3

示例請! – Demodave

48

這是你需要添加,使其工作。

response.setHeader("Access-Control-Allow-Origin", "*"); 
    response.setHeader("Access-Control-Allow-Credentials", "true"); 
    response.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT"); 
    response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"); 

瀏覽器發送一個預檢請求(具有方法類型OPTIONS),以檢查是否該服務器上的所述服務允許被從瀏覽器上的不同的域訪問。爲了響應預檢請求,如果你注入了上面的頭文件,瀏覽器就會明白,進行進一步的調用是可以的,我將得到對我實際的GET/POST調用的有效響應。您可以通過使用Access-Control-Allow-Origin「,」localhost,xvz.com「而不是*來約束授予訪問權限的域。(*將授予對所有域的訪問權限)

+0

感謝您的輸入@manisharora我將保持安妮的問題作爲接受的答案,但我upvoted你的以及答案的第一種格式。 – mibbit

+4

你不能將'...- Origin'和'''' - Credentials'結合起來。對於非憑證請求,它不會失敗,但它對於憑證請求也不起作用。查看我在答案中發佈的鏈接。 – Anne

+0

感謝Manish Arora,我在你的API中使用了你的解決方案,並且工作。 HttpContext.Response.Headers.Add(「Access-Control-Allow-Methods」,「GET,HEAD,OPTIONS,POST,PUT」); HttpContext.Response.Headers.Add(「Access-Control-Allow-Headers」,「Access-Control-Allow-Headers,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,訪問控制請求報頭「); HttpContext.Response.Headers.Add(「Access-Control-Allow-Origin」,「http:// localhost:4200」); – Ramakrishnankt

35

此問題通過

"Origin, X-Requested-With, Content-Type, Accept, Authorization" 

特別是在我的項目(express.js /的NodeJS)

app.use(function(req, res, next) { 
    res.header("Access-Control-Allow-Origin", "*"); 
    res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT"); 
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); 
    next(); 
}); 

更新:

每次錯誤:Access-Control-Allow-Headers is not allowed by itself in preflight response錯誤你可以看到什麼錯chrome developer tool
enter image description here

上述錯誤缺少Content-Type所以加串Content-TypeAccess-Control-Allow-Headers

+0

這不適用於所有人。 Access-Control-Request-Headers的值可能因環境而異。訪問服務器上的請求對象並轉儲「Access-Control-Request-Headers」頭的值。然後,複製/粘貼到你的response.setHeader(「Access-Control-Allow-Headers」,「{paste here}」) –

+0

@OutfastSource thansk我已經更新了答案 –

+0

也請確保你的拼寫授權美國人的方式不是英國人的方式。這是我一生中的半小時,我不會回來。 Thx美國! [嘆氣] – geoidesic

4

要添加到其他的答案。我有同樣的問題,這是我在Express服務器用來允許REST調用的代碼:

app.all('*', function(req, res, next) { 
    res.header('Access-Control-Allow-Origin', 'URLs to trust of allow'); 
    res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); 
    res.header('Access-Control-Allow-Headers', 'Content-Type'); 
    if ('OPTIONS' == req.method) { 
    res.sendStatus(200); 
    } else { 
     next(); 
    } 
    }); 

這段代碼基本上都爲攔截所有的請求,並增加了CORS標頭,然後用我的正常路線繼續。當有OPTIONS請求時,它只響應CORS標題。

10

接受的答案是好的,但我很難理解它。所以這裏有一個簡單的例子來澄清它。

在我的ajax請求中,我有一個標準的授權標頭。

$$(document).on('ajaxStart', function(e){ 
    var auth_token = localStorage.getItem(SB_TOKEN_MOBILE); 
    if(auth_token) { 
     var xhr = e.detail.xhr; 

     xhr.setRequestHeader('**Authorization**', 'Bearer ' + auth_token); 
    } 

此代碼會在問題中產生錯誤。我曾在我的服務器的NodeJS做的是增加在授權允許標題:

res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,**Authorization**'); 
0

我想補充的是,你可以把這些標題也的WebPack配置文件。當我運行webpack dev服務器時,我需要它們。

devServer: { 
    headers: { 
     "Access-Control-Allow-Origin": "*", 
     "Access-Control-Allow-Credentials": "true", 
     "Access-Control-Allow-Methods": "GET,HEAD,OPTIONS,POST,PUT", 
     "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Authorization" 
}, 
3

我只是遇到這個問題我自己,在ASP.NET的背景下,確保你的web.config看起來是這樣的:

<system.webServer> 
<modules> 
    <remove name="FormsAuthentication" /> 
</modules> 

<handlers> 
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> 
    <!--<remove name="OPTIONSVerbHandler"/>--> 
    <remove name="TRACEVerbHandler" /> 
    <!-- 
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> 
    --> 
</handlers> 

<httpProtocol> 
    <customHeaders> 
    <add name="Access-Control-Allow-Origin" value="*" /> 
    <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" /> 
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /> 
    </customHeaders> 
</httpProtocol> 

通知爲Access-Control-Allow-Headers授權值鍵。我錯過了授權值,這個配置解決了我的問題。

2

在Chrome中:

Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers in preflight response.

對於我來說,這個錯誤是由尾隨空間在這個調用的URL觸發。

jQuery.getJSON(url, function(response, status, xhr) { 
    ... 
} 
3

非常好,我用這個在硅石項目

$app->after(function (Request $request, Response $response) { 
     $response->headers->set('Access-Control-Allow-Origin', '*'); 
     $response->headers->set("Access-Control-Allow-Credentials", "true"); 
     $response->headers->set("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT"); 
     $response->headers->set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); 
    }); 
+1

儘管這段代碼可能會回答這個問題,但提供關於如何解決問題和/或爲什麼解決問題的額外上下文會提高答案的長期價值。 – Badacadabra

0

這同樣的問題我面臨。

我做了一個簡單的改變。

<modulename>.config(function($httpProvider){ 
    delete $httpProvider.defaults.headers.common['X-Requested-With']; 
}); 
相關問題