LarryDpk
发布于 2021-02-28 / 1167 阅读 / 0 评论 / 0 点赞

CORS跨源资源共享概念及配置(Kubernetes Ingress和Spring Cloud Gateway)

1 跨源资源共享CORS

跨源资源共享 (CORS) (或通俗地译为跨域资源共享)是一种基于HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它origin(域,协议和端口),这样浏览器可以访问加载这些资源。

首先要明确的是,浏览器访问资源才会有CORS的存在,如果通过其它HTTP Client等代码,就不会出现。CORS简单一点讲就是当在浏览器地址栏的源Origin与所访问的资源的地址的源不同,就是跨源了。比如在前后端分离的开发中,UI的地址为http://localhost:3000,而服务的地址为http://localhost:8080,通过JavaScript获取服务的数据,就需要跨源。

1.1 预检preflight

对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨源请求。服务器确认允许之后,才发起实际的 HTTP 请求。

所以,CORS是需要服务器端打开的一个特性,而不是客户端

对于简单请求,不需要预检:

预检一般是通过OPTION方法来进行:

需要注意:

请求的首部中携带了 Cookie 信息(credentials:include),如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。

2 kubernetes ingress打开CORS

可以在ingress层面打开CORS,而不用在应用层面。配置如下:

annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS, DELETE"
nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,X-CustomHeader,X-LANG,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Api-Key,X-Device-Id,Access-Control-Allow-Origin"

当考虑到某些场景不能使allow-origin*,所以可以按下面这样配置:

nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
	more_set_headers "Access-Control-Allow-Origin: $http_origin";

3 spring cloud gateway打开CORS

可以通过配置properties来实现,也可以通过Java配置WebFilter来实现。

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "https://www.pkslow.com"
            allowedMethods:
            - GET

Java的方式大致如下:

@Bean
CorsWebFilter corsWebFilter() {
    CorsConfiguration corsConfig = new CorsConfiguration();
    corsConfig.setAllowedOrigins(Arrays.asList("https://www.pkslow.com"));
    corsConfig.setMaxAge(8000L);
    corsConfig.addAllowedMethod("PUT");

    UrlBasedCorsConfigurationSource source =
      new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfig);

    return new CorsWebFilter(source);
}

参考:

Mozilla CORS

跨域资源共享 CORS 详解 阮一峰

stackoverflow ingress cors

FEATURE REQUEST: set cors access-control-allow-origin to incoming origin

Ingress annotation

CORS with Spring

Spring Webflux and CORS

spring cloud gateway docs