跨域资源共享(CORS)是一种机制,它使用额外的HTTP头来告诉浏览器让运行在一个域名上的Web应用可以访问来自不同源服务器上的指定资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求另外一个资源时,资源会发起一个跨域HTTP请求。
比如,站点http://domain-a.com 的某HTML页面通过<img>的src请求http://domain-b.com/image.jpg 。出于安全原因,浏览器限制跨域HTTP请求。可以通过配置CORS头来解除这种限制。更深入的内容可以参考如下两篇文章:
·http://www.ruanyifeng.com/blog/2016/04/cors.html
·https://developer.mozilla.org/zh-CN/docs/Web/HTTP/AccesscontrolCORS
Istio提供了CORS的配置,我们可以在VirtualService中配置CORS。
服务service-go配置CORS示例如下:
1 apiVersion: networking.istio.io/v1alpha3 2 kind: VirtualService 3 metadata: 4 name: service-go-cors 5 spec: 6 hosts: 7 - service-go 8 http: 9 - route: 10 - destination: 11 host: service-go 12 corsPolicy: 13 allowOrigin: 14 - http://www.will.com 15 allowMethods: 16 - POST 17 - GET 18 allowHeaders: 19 - X-Custom-Header 20 exposeHeaders: 21 - X-Expose-Header 22 maxAge: 24h 23 allowCredentials: false
第12~23行定义了服务service-go的CORS设置,allowOrigin表示允许跨域的域名,allowMethods表示允许跨域的HTTP方法,allowHeaders表示在请求时允许携带的请求头,exposeHeaders表示允许暴露的请求响应头,maxAge表示跨域预检查的缓存时间,allowCredentials表示是否允许发送Cookie。
【实验】
1)创建测试Pod:
$ kubectl apply -f kubernetes/dns-test.yaml
2)创建service-go服务的CORS规则:
$ kubectl apply -f istio/miscellaneous/virtual-service-go-cors.yaml
3)简单请求访问测试:
$ kubectl exec dns-test -c dns-test -- curl -sv -H "Origin: http://www.will.com" http://service-go/env > GET /env HTTP/1.1 > User-Agent: curl/7.35.0 > Host: service-go > Accept: */* > Origin: http://www.will.com > {"message":"go v2"}< HTTP/1.1 200 OK < content-type: application/json; charset=utf-8 < date: Sat, 19 Jan 2019 05:54:22 GMT < content-length: 19 < x-envoy-upstream-service-time: 18 < server: envoy < access-control-allow-origin: http://www.will.com < access-control-expose-headers: X-Expose-Header < { [data not shown] $ kubectl exec dns-test -c dns-test -- curl -sv -H "Origin: http://not-allowed-origin.will.com" http://service-go/env > GET /env HTTP/1.1 > User-Agent: curl/7.35.0 > Host: service-go > Accept: */* > Origin: http://not-allowed-origin.will.com > {"message":"go v2"}< HTTP/1.1 200 OK < content-type: application/json; charset=utf-8 < date: Sat, 19 Jan 2019 05:55:22 GMT < content-length: 19 < x-envoy-upstream-service-time: 1 < server: envoy < { [data not shown]
4)非简单请求访问测试。
预检请求:
$ kubectl exec dns-test -c dns-test -- curl -sv -X OPTIONS -H "Origin: http://www.will.com" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: X-Custom-Header" http://service-go/env > OPTIONS /env HTTP/1.1 > User-Agent: curl/7.35.0 > Host: service-go > Accept: */* > Origin: http://www.will.com > Access-Control-Request-Method: GET > Access-Control-Request-Headers: X-Custom-Header > < HTTP/1.1 200 OK < access-control-allow-origin: http://www.will.com < access-control-allow-methods: POST,GET < access-control-allow-headers: X-Custom-Header < access-control-max-age: 24h0m0s < access-control-expose-headers: X-Expose-Header < date: Sat, 19 Jan 2019 05:56:18 GMT < server: envoy < content-length: 0 < $ kubectl exec dns-test -c dns-test -- curl -sv -X OPTIONS -H "Origin: http://not-allowed-origin.will.com" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: X-Custom-Header" http://service-go/env > OPTIONS /env HTTP/1.1 > User-Agent: curl/7.35.0 > Host: service-go > Accept: */* > Origin: http://not-allowed-origin.will.com > Access-Control-Request-Method: GET > Access-Control-Request-Headers: X-Custom-Header > < HTTP/1.1 404 Not Found < date: Sat, 19 Jan 2019 05:57:32 GMT < server: envoy < content-length: 0 < x-envoy-upstream-service-time: 1 <
正常请求:
$ kubectl exec dns-test -c dns-test -- curl -sv -H "Origin: http://www.will.com" -H "X-Custom-Header: value" http://service-go/env > GET /env HTTP/1.1 > User-Agent: curl/7.35.0 > Host: service-go > Accept: */* > Origin: http://www.will.com > X-Custom-Header: value > {"message":"go v2"}< HTTP/1.1 200 OK < content-type: application/json; charset=utf-8 < date: Sat, 19 Jan 2019 05:57:58 GMT < content-length: 19 < x-envoy-upstream-service-time: 1 < server: envoy < access-control-allow-origin: http://www.will.com < access-control-expose-headers: X-Expose-Header < { [data not shown] $ kubectl exec dns-test -c dns-test -- curl -sv -H "Origin: http://not-allowed-origin.will.com" -H "X-Custom-Header: value" http://service-go/env > GET /env HTTP/1.1 > User-Agent: curl/7.35.0 > Host: service-go > Accept: */* > Origin: http://not-allowed-origin.will.com > X-Custom-Header: value > {"message":"go v2"}< HTTP/1.1 200 OK < content-type: application/json; charset=utf-8 < date: Sat, 19 Jan 2019 05:58:40 GMT < content-length: 19 < x-envoy-upstream-service-time: 17 < server: envoy < { [data not shown]
从上面的请求测试可以得出如下的结论:当使用允许的域名进行跨域请求时,返回的响应头中都会有浏览器跨域请求需要的Access-Control-Allow-Origin等字段。当使用了其他不被允许的域名进行跨域资源请求时,请求的响应中并不包含浏览器跨域请求资源时需要的响应头。
5)清理:
$ kubectl delete -f kubernetes/dns-test.yaml $ kubectl delete -f istio/miscellaneous/virtual-service-go-cors.yaml