當請求ACK叢集服務時,報blocked by CORS policy錯誤,是因為瀏覽器只允許網頁訪問相同協議、網域名稱和連接埠的資源。比如網站https://example.com無法直接存取不同網域名稱的資源https://api.example.com。通過給Nginx Ingress配置註解(Annotations),啟用跨域資源共用(CORS)策略,從而允許特定的跨域請求。
工作原理
CORS請求分為兩種類型:簡單請求和預檢請求。簡單請求可以直接發送,預檢請求必須先獲得許可才能發送主請求。
如果滿足以下任何一種情況,系統將對請求執行預檢:
請求使用的是
GET、HEAD、POST以外的方法。請求使用
POST方法且Content-Type不是text/plain、application/x-www-form-urlencoded或multipart/form-data。請求設定了自訂頭部。
當瀏覽器向Nginx Ingress發出簡單請求時,會發生以下過程:
瀏覽器將
Origin頭部添加到請求中。Origin頭部包含相應資源的來源,例如Origin: https://example.com。Nginx Ingress Controller將請求的HTTP方法以及
Origin頭部的值與CORS配置進行比較,尋找匹配項。如果存在匹配項,將在響應中包含Access-Control-Allow-Origin頭部。Access-Control-Allow-Origin頭部包含初始請求的Origin頭部的值。瀏覽器接收響應並檢查
Access-Control-Allow-Origin值是否與原始請求的網域名稱匹配。如果匹配,則請求成功。如果不匹配,或者響應中不存在Access-Control-Allow-Origin頭部,則請求失敗。
預檢請求首先執行以下步驟,成功後再執行與簡單請求相同的過程:
瀏覽器發送一個
OPTIONS請求,包含主請求的方法(Access-Control-Request-Method)和頭部(Access-Control-Request-Headers)資訊。Nginx Ingress根據CORS配置檢查請求的方法和頭部是否被允許。如果預檢請求中的任何方法或標題值未包含在目標資源允許的方法和標題集合中,請求將失敗,並且不會發送主請求。
操作步驟
步驟一:配置CORS
登入Container Service管理主控台,在左側導覽列選擇叢集列表。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇。
在路由頁面操作列中,單擊YAML編輯。
根據具體業務情境,配置Nginx Ingress。常用配置說明,請參考Nginx Ingress Controller中常用CORS配置。
攜帶憑證或Cookie的跨域情境
適用於常見的前後端分離情境:前端應用(https://example.com、https://app.example.com)需要攜帶Cookie或Authorization要求標頭等憑證訪問後端API(https://api.example.com)。
在YAML中添加以下樣本中annotations配置內容。樣本為example.com、app.example.com源域的GET、POST等方法開啟跨域訪問。
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頭 | 樣本 |
| 是否啟用CORS策略。 |
| |
| 哪些域可以訪問資源(可配置多個域)。 | Access-Control-Allow-Origin |
|
| 允許的方法類型,例如GET、POST、PUT等。 | Access-Control-Allow-Methods |
|
| 允許的自訂要求標頭欄位。 | Access-Control-Allow-Headers |
|
| 是否可以發送帶有憑證的請求(如Cookie、HTTP認證資訊)。 | Access-Control-Allow-Credentials |
|
| 哪些回應標頭可以在瀏覽器中訪問。 此註解需要 Nginx Ingress Controller v0.44 或更高版本 | Access-Control-Expose-Headers |
|
| 瀏覽器緩衝預檢請求結果的最大時間(單位:秒),較長的緩衝時間可減少預檢請求頻率。如對安全性要求更高,可適當調低此值。 | Access-Control-Max-Age |
|
常見問題
配置完成後,仍出現跨域訪問報錯,如何排查?
檢查瀏覽器開發人員工具中的網路請求或 Nginx Ingress Controller 的日誌,核實請求的來源域(Origin)、要求方法和要求標頭等,確認它們是否在 Ingress 的 CORS 允許範圍內。
以下樣本為典型的跨域報錯輸出。請求使用了POST方法,但該方法未在Access-Control-Allow-Methods回應標頭中被允許。
Method POST is not allowed by Access-Control-Allow-Methods in preflight responseAccess 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-Control、Content-Language、Content-Type、Expires、Last-Modified和Pragma。服務端返回的任何自訂頭欄位(如X-Request-ID),在沒有配置的情況下,對用戶端JavaScript都是不可見的。
nginx.ingress.kubernetes.io/cors-expose-headers註解用於設定Access-Control-Expose-Headers的HTTP回應標頭,以決定哪些非標準回應標頭欄位可以通過用戶端的JavaScript代碼擷取。具體配置,請參考攜帶憑證或Cookie的跨域情境。
相關文檔
文中樣本僅包含Nginx Ingress Controller常用CORS註解。更多資訊,請參考Enable CORS。