您目前查看的是 Apigee Edge 說明文件。
前往 Apigee X 說明文件。 info
CORS (跨源資源共享) 是一種標準機制,可讓您在網頁中執行 JavaScript XMLHttpRequest (XHR) 呼叫,以便與非來源網域的資源進行互動。CORS 是常見的解決方案,可因應所有瀏覽器強制執行的「同源政策」。舉例來說,如果您從瀏覽器執行的 JavaScript 程式碼,對 Twitter API 進行 XHR 呼叫,該呼叫就會失敗。這是因為向瀏覽器提供網頁的網域,與提供 Twitter API 的網域不同。CORS 允許伺服器「選擇加入」跨源資源共用,藉此解決這個問題。
影片:觀看短片,瞭解如何在 API Proxy 上啟用 CORS。
CORS 的典型用途
下列 JQuery 程式碼會呼叫虛構的目標服務。如果從瀏覽器 (網頁) 的環境中執行,由於同源政策,呼叫會失敗:
<script> var url = "http://service.example.com"; $(document).ready(function(){ $("button").click(function(){ $.ajax({ type:"GET", url:url, async:true, dataType: "json", success: function(json) { // Parse the response. // Do other things. }, error: function(xhr, status, err) { // This is where we end up! } }); }); }); </script>
解決這個問題的方法之一,是建立 Apigee API Proxy,在後端呼叫服務 API。請注意,Edge 位於用戶端 (本例中為瀏覽器) 和後端 API (服務) 之間。由於 API Proxy 是在伺服器上執行,而非在瀏覽器中,因此能夠順利呼叫服務。接著,您只需要將 CORS 標頭附加至 TargetEndpoint 回應。只要瀏覽器支援 CORS,這些標頭就會向瀏覽器發出訊號,表示可以「放寬」同源政策,允許跨源 API 呼叫成功。
建立支援 CORS 的 Proxy 後,您可以在用戶端程式碼中呼叫 API Proxy 網址,而非後端服務。例如:
<script> var url = "http://myorg-test.apigee.net/v1/example"; $(document).ready(function(){ $("button").click(function(){ $.ajax({ type:"GET", url:url, async:true, dataType: "json", success: function(json) { // Parse the response. // Do other things. }, error: function(xhr, status, err) { // This time, we do not end up here! } }); }); }); </script>
將「新增 CORS」政策附加至新的 API Proxy
建立 API Proxy 時,將「Add CORS」政策附加至 API Proxy,即可為 API Proxy 新增 CORS 支援。如要新增這項政策,請在「Build a Proxy」精靈的「Security」頁面中,選取「Add CORS headers」核取方塊。
選取這個核取方塊後,系統會自動新增名為「Add CORS」的政策,並附加至 TargetEndpoint 回應預先流程,如下圖所示:

「新增 CORS 政策」會以 AssignMessage 政策的形式實作,在回應中新增適當的標頭。基本上,標頭會讓瀏覽器知道要與哪些來源共用資源、接受哪些方法等等。如要進一步瞭解這些 CORS 標頭,請參閱跨源資源共享 W3C 建議。
請按照下列方式修改政策:
- 將
content-type和authorization標頭 (支援基本驗證或 OAuth2 時必須使用) 新增至Access-Control-Allow-Headers標頭,如下方程式碼片段所示。 - 如要使用 OAuth2 驗證,您可能需要採取步驟,修正不符合 RFC 的行為。
- 建議您使用
<Set>設定 CORS 標頭,而非<Add>,如下方摘錄內容所示。 使用<Add>時,如果Access-Control-Allow-Origin標頭已存在,您會收到下列錯誤:The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.詳情請參閱「 CORS Error : header contains multiple values '*, *', but only one is allowed」。
<AssignMessage async="false" continueOnError="false" enabled="true" name="add-cors"> <DisplayName>Add CORS</DisplayName> <FaultRules/> <Properties/> <Set> <Headers> <Header name="Access-Control-Allow-Origin">{request.header.origin}</Header> <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, content-type, authorization</Header> <Header name="Access-Control-Max-Age">3628800</Header> <Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header> </Headers> </Set> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> <AssignTo createNew="false" transport="http" type="response"/> </AssignMessage>
在現有 Proxy 中新增 CORS 標頭
您需要手動建立新的 Assign Message 政策,並將上一節列出的 Add CORS 政策程式碼複製到其中。然後,將政策附加至 API Proxy 的 TargetEndpoint 回應預先流程。您可以視需要修改標頭值。如要進一步瞭解如何建立及附加政策,請參閱「什麼是政策?」。
處理 CORS 預檢要求
CORS 預檢是指將要求傳送至伺服器,確認伺服器是否支援 CORS。典型的預檢回應包括伺服器會接受哪些來源的 CORS 要求、CORS 要求支援的 HTTP 方法清單、可用於資源要求中的標頭、預檢回應的快取時間上限等。如果服務未指出支援 CORS,或不希望接受來自用戶端來源的跨源要求,瀏覽器就會強制執行跨源政策,且用戶端發出的任何跨網域要求都會失敗,無法與該伺服器上託管的資源互動。
一般來說,CORS 預檢要求會使用 HTTP OPTIONS 方法。支援 CORS 的伺服器收到 OPTIONS 要求時,會傳回一組 CORS 標頭給用戶端,指出其 CORS 支援等級。完成交握後,用戶端就會知道允許從非原始網域要求哪些內容。
如要進一步瞭解預檢,請參閱 Cross-Origin Resource Sharing W3C Recommendation。此外,您也可以參考許多關於 CORS 的網誌和文章。
Apigee 不會隨附 CORS 預檢解決方案,但您可以實作,如本節所述。目標是讓 Proxy 在條件式流程中評估 OPTIONS 要求。Proxy 接著會將適當的回應傳回給用戶端。
讓我們看看範例流程,然後討論處理預檢要求的各個部分:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
<Description/>
<Flows>
<Flow name="OptionsPreFlight">
<Request/>
<Response>
<Step>
<Name>add-cors</Name>
</Step>
</Response>
<Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
</Flow>
</Flows>
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<HTTPProxyConnection>
<BasePath>/v1/cnc</BasePath>
<VirtualHost>default</VirtualHost>
<VirtualHost>secure</VirtualHost>
</HTTPProxyConnection>
<RouteRule name="NoRoute">
<Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
</RouteRule>
<RouteRule name="default">
<TargetEndpoint>default</TargetEndpoint>
</RouteRule>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
</ProxyEndpoint>這個 ProxyEndpoint 的主要部分如下:
- 系統會為 OPTIONS 要求建立具有條件的 NULL 目標 RouteRule。請注意,系統未指定 TargetEndpoint。如果收到 OPTIONS 要求,且 Origin 和 Access-Control-Request-Method 要求標頭不是空值,Proxy 會立即在回應中將 CORS 標頭傳回給用戶端 (略過實際的預設「後端」目標)。如要進一步瞭解流程條件和 RouteRule,請參閱「含有流程變數的條件」。
<RouteRule name="NoRoute"> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </RouteRule> - 如果收到 OPTIONS 要求,且 Origin 和 Access-Control-Request-Method 要求標頭不是空值,系統就會建立 OptionsPreFlight 流程,將含有 CORS 標頭的「新增 CORS 政策」新增至流程。
<Flow name="OptionsPreFlight"> <Request/> <Response> <Step> <Name>add-cors</Name> </Step> </Response> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </Flow>
使用範例 CORS 解決方案
您可以在 GitHub 上找到以共用流程實作的 CORS 解決方案範例。 將共用流程套件匯入環境,並使用流程掛鉤附加,或直接附加至 API Proxy 流程。詳情請參閱範例隨附的 CORS-Shared-FLow README 檔案。