更新时间:2024-10-15 GMT+08:00
分享

为Nginx Ingress配置跨域访问

在Web开发中,由于浏览器的同源策略,一个域下的网页通常不能直接请求另一个域下的资源。CORS(跨资源共享,Cross-Origin Resource Sharing)提供了一种安全的方式来绕过这个限制,允许跨域请求。

使用CORS允许跨域访问的场景较多,可能的场景如下:

  • 前后端分离:前端应用部署在一个域名下(如 frontend.example.com),而后端API服务使用另一个域名(如 api.example.com),前端应用在尝试从API服务获取数据时会遇到跨域资源共享问题,需要配置CORS允许跨域访问。
  • 第三方服务集成:网站可能需要调用第三方服务(例如地图服务、社交平台登录等)的API接口,则需要配置CORS允许跨域访问。
  • 使用内容分发网络CDN:静态资源可能通过CDN提供,而CDN域名与主站域名不同,需要使用跨域访问来加载这些资源。

为Nginx Ingress配置跨域访问示例

本文以一个前端应用程序(frontend.example.com)与后端API服务(api.example.com)通信为例,在Ingress资源的Annotations部分添加指定注解配置跨域访问,注解详情请参见Enable CORS

为Nginx Ingress配置跨域访问示例如下:

apiVersion: networking.k8s.io/v1 
kind: Ingress 
metadata:
  name: test-ingress 
  namespace: default 
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"     # 启用CORS跨域访问
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"  # 允许访问的域
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, DELETE, PATCH, OPTIONS"  # 允许的HTTP请求方法
    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-expose-headers: "Content-Length,Content-Range"  # 需要公开的响应头
    nginx.ingress.kubernetes.io/cors-max-age: "3600"  # 预检请求的缓存时长
spec:
  rules:
    - host: api.example.com 
      http:
        paths:
          - path: /
            backend:
              service:
                name: example
                port:
                  number: 80
            property:
              ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH
            pathType: ImplementationSpecific
  ingressClassName: nginx
表1 跨域访问配置说明

参数

说明

配置示例

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响应头的值,表示允许访问的域。

格式为“http(s)://example.com”“http(s)://example.com:port”,可填写多个值,以英文逗号分割。

同时支持使用通配符,例如:

  • “*”表示允许所有域访问。
  • 填写一级泛域名,如“http(s)://*.example.com”表示允许该域名下的所有子域名访问。
须知:

出于安全考虑,建议指定确切的域名,防止未经授权的域访问敏感资源。

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

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

指定Access-Control-Allow-Methods响应头的值,表示允许的HTTP请求方法。

可填写多个值,以英文逗号分割。

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

指定Access-Control-Allow-Credentials响应头的值,表示是否允许发送凭据(如Cookies)。

取值如下:

  • true:允许发送凭据。
  • false:不允许发送凭据。
须知:

由于安全策略限制,当Access-Control-Allow-Credentials设置为true时,Access-Control-Allow-Origin不能设置为允许所有域名访问,即不能设为通配符"*",防止未经授权的域访问敏感资源,例如携带用户凭证信息的Cookies或者Authorization头部等。

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

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

指定Access-Control-Expose-Headers响应头的值,表示可以被跨域请求读取的自定义响应头部,例如通过客户端的JavaScript代码获取非标准响应头字段。

默认情况下出于安全考虑,浏览器在处理跨域请求时只能访问标准的响应头,包括Cache-Control、Content-Language、Content-Type、Expires、Last-Modified和Pragma。

可填写多个值,以英文逗号分割。

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

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

指定Access-Control-Max-Age响应头的值,表示CORS预检请求的缓存时长。

该参数值应该根据实际需求合理设置。如果设置得太短,可能会导致频繁的预检请求;如果设置得太长,可能会在CORS策略更新后延迟生效。

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

验证跨域访问配置是否生效

使用curl命令行工具发送跨域请求,并检查响应头部。

curl -X OPTIONS -H 'Origin: {源站点}' {Ingress访问URL} -i

例如,本示例中源站点为frontend.example.com,访问的Ingress URL为api.example.com,则命令如下:

curl -X OPTIONS -H 'Origin: frontend.example.com' api.example.com -i

回显如下,跨域访问会在原始后端响应中添加Access-Control-**相关的请求头:

HTTP/1.1 200 OK 
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS 
Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range 
Access-Control-Expose-Headers: Content-Length,Content-Range 
Access-Control-Allow-Credentials: true 
Content-Type: application/json

相关文档