当请求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
登录容器服务管理控制台,在左侧导航栏选择集群列表。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择 。
在路由页面操作列中,单击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 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-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。