全部產品
Search
文件中心

Container Service for Kubernetes:Nginx Ingress跨網域設定

更新時間:Sep 21, 2025

當請求ACK叢集服務時,報blocked by CORS policy錯誤,是因為瀏覽器只允許網頁訪問相同協議、網域名稱和連接埠的資源。比如網站https://example.com無法直接存取不同網域名稱的資源https://api.example.com。通過給Nginx Ingress配置註解(Annotations),啟用跨域資源共用(CORS)策略,從而允許特定的跨域請求。

工作原理

CORS請求分為兩種類型:簡單請求和預檢請求。簡單請求可以直接發送,預檢請求必須先獲得許可才能發送主請求。

如果滿足以下任何一種情況,系統將對請求執行預檢:

  • 請求使用的是GETHEADPOST以外的方法。

  • 請求使用POST方法且 Content-Type 不是 text/plainapplication/x-www-form-urlencoded 或 multipart/form-data

  • 請求設定了自訂頭部。

當瀏覽器向Nginx Ingress發出簡單請求時,會發生以下過程:

  1. 瀏覽器將Origin頭部添加到請求中。Origin頭部包含相應資源的來源,例如Origin: https://example.com

  2. Nginx Ingress Controller將請求的HTTP方法以及Origin頭部的值與CORS配置進行比較,尋找匹配項。如果存在匹配項,將在響應中包含Access-Control-Allow-Origin頭部。Access-Control-Allow-Origin頭部包含初始請求的Origin頭部的值。

  3. 瀏覽器接收響應並檢查Access-Control-Allow-Origin值是否與原始請求的網域名稱匹配。如果匹配,則請求成功。如果不匹配,或者響應中不存在 Access-Control-Allow-Origin頭部,則請求失敗。

預檢請求首先執行以下步驟,成功後再執行與簡單請求相同的過程:

  1. 瀏覽器發送一個OPTIONS請求,包含主請求的方法(Access-Control-Request-Method)和頭部(Access-Control-Request-Headers)資訊。

  2. Nginx Ingress根據CORS配置檢查請求的方法和頭部是否被允許。如果預檢請求中的任何方法或標題值未包含在目標資源允許的方法和標題集合中,請求將失敗,並且不會發送主請求。

操作步驟

步驟一:配置CORS

  1. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇網路 > 路由

  3. 路由頁面操作列中,單擊YAML編輯

  4. 根據具體業務情境,配置Nginx Ingress。常用配置說明,請參考Nginx Ingress Controller中常用CORS配置

攜帶憑證或Cookie的跨域情境

適用於常見的前後端分離情境:前端應用(https://example.comhttps://app.example.com)需要攜帶Cookie或Authorization要求標頭等憑證訪問後端API(https://api.example.com)。

在YAML中添加以下樣本中annotations配置內容。樣本為example.comapp.example.com源域的GETPOST等方法開啟跨域訪問。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress-secure
  annotations:
    # 啟用 CORS
    nginx.ingress.kubernetes.io/enable-cors: "true"
    # 允許攜帶憑證(如 Cookie、Authorization 要求標頭)
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
    # 精確指定允許發起跨域請求的來源域。嚴禁在憑證模式下使用 "*"
    nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com, https://app.example.com"
    # 允許的 HTTP 方法
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
    # 允許的要求標頭,必須包含業務所需的自訂頭(如 Authorization)
    nginx.ingress.kubernetes.io/cors-allow-headers: "Content-Type, Authorization"
    # 指定哪些自訂回應標頭欄位暴露給前端
    nginx.ingress.kubernetes.io/cors-expose-headers: "X-Request-ID, Content-Length, Content-Range" 
    # 預檢請求最大緩衝時間長度(樣本值86400秒,即24小時)	
    nginx.ingress.kubernetes.io/cors-max-age: "86400"
...

無需憑證的跨域情境

適用於公開、唯讀、無需任何身分識別驗證的請求情境。

在YAML中添加以下annotations配置內容。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress-secure
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
    # 當 origin 為 "*" 時,credentials 必須為 false
    nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, HEAD"
...

步驟二:驗證跨網域設定

使用curl類比瀏覽器發送OPTIONS預檢請求。

curl -i -X OPTIONS 'https://api.example.com/your/path' \
  -H 'Origin: https://app.example.com' \
  -H 'Access-Control-Request-Method: POST' \
  -H 'Access-Control-Request-Headers: Content-Type, Authorization'

預期輸出:正常情況應返回一個 2xx 的狀態代碼(通常是 204 No Content 或 200 OK)。

HTTP/2 204
date: Fri, 12 Sep 2025 03:51:12 GMT
access-control-allow-origin: https://example.com, https://app.example.com
access-control-allow-credentials: true
access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
access-control-allow-headers: Content-Type, Authorization

檢查回應標頭中 access-control-allow-* 各項的值,是否與 Ingress 資源中配置的 nginx.ingress.kubernetes.io/cors-* 值一致。

Nginx Ingress Controller中常用CORS配置

註解

描述

關聯HTTP頭

樣本

nginx.ingress.kubernetes.io/enable-cors

是否啟用CORS策略。

nginx.ingress.kubernetes.io/enable-cors: "true"

nginx.ingress.kubernetes.io/cors-allow-origin

哪些域可以訪問資源(可配置多個域)。

Access-Control-Allow-Origin

nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"

nginx.ingress.kubernetes.io/cors-allow-methods

允許的方法類型,例如GET、POST、PUT等。

Access-Control-Allow-Methods

nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, DELETE, PATCH, OPTIONS"

nginx.ingress.kubernetes.io/cors-allow-headers

允許的自訂要求標頭欄位。

Access-Control-Allow-Headers

nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range"

nginx.ingress.kubernetes.io/cors-allow-credentials

是否可以發送帶有憑證的請求(如Cookie、HTTP認證資訊)。

Access-Control-Allow-Credentials

nginx.ingress.kubernetes.io/cors-allow-credentials: "true"

nginx.ingress.kubernetes.io/cors-expose-headers

哪些回應標頭可以在瀏覽器中訪問。

此註解需要 Nginx Ingress Controller v0.44 或更高版本

Access-Control-Expose-Headers

nginx.ingress.kubernetes.io/cors-expose-headers: "Content-Length,Content-Range"

nginx.ingress.kubernetes.io/cors-max-age

瀏覽器緩衝預檢請求結果的最大時間(單位:秒),較長的緩衝時間可減少預檢請求頻率。如對安全性要求更高,可適當調低此值。

Access-Control-Max-Age

nginx.ingress.kubernetes.io/cors-max-age: "86400"

常見問題

配置完成後,仍出現跨域訪問報錯,如何排查?

檢查瀏覽器開發人員工具中的網路請求或 Nginx Ingress Controller 的日誌,核實請求的來源域(Origin)、要求方法和要求標頭等,確認它們是否在 Ingress 的 CORS 允許範圍內。

以下樣本為典型的跨域報錯輸出。請求使用了POST方法,但該方法未在Access-Control-Allow-Methods回應標頭中被允許。

  • Method POST is not allowed by Access-Control-Allow-Methods in preflight response

  • Access to fetch at 'https://api.example.com/data' from origin 'https://app.example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: xxxx.

在設定了nginx.ingress.kubernetes.io/cors-allow-credentials: "true"後,是否允許將nginx.ingress.kubernetes.io/cors-allow-origin配置為"*"?

不允許。這是由W3C規範和瀏覽器安全性原則強制規定的。當一個請求需要攜帶憑證(如 Cookie)時,伺服器必須明確指定它信任的來源域,而不能使用萬用字元 *。這是為了防止任何惡意網站都能利用使用者的登入憑證向伺服器發起請求,從而避免潛在的安全風險。

如何為同一網域名稱下的不同路徑(例如 /api/public/*/api/private/*)設定不同的 CORS 策略?

Nginx Ingress 的 CORS 註解是 Ingress 資源層級的,不支援路徑級配置。標準做法是為需要不同 CORS 策略的路徑組建立獨立的 Ingress 資源。例如,建立一個 api-public-ingress.yaml 和一個 api-private-ingress.yaml,並為它們分別設定不同的 CORS 註解。

用戶端如何擷取服務端返回的自訂回應標頭?

預設情況下,瀏覽器在處理跨域請求時只能訪問標準的回應標頭,包括Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma。服務端返回的任何自訂頭欄位(如X-Request-ID),在沒有配置的情況下,對用戶端JavaScript都是不可見的。

nginx.ingress.kubernetes.io/cors-expose-headers註解用於設定Access-Control-Expose-Headers的HTTP回應標頭,以決定哪些非標準回應標頭欄位可以通過用戶端的JavaScript代碼擷取。具體配置,請參考攜帶憑證或Cookie的跨域情境

相關文檔