当一个客户端去访问另一个不同域名或者同域名不同端口的服务时,就会发出跨域请求。如果此时该服务不允许其进行跨域资源访问,那么就会因为跨域问题而导致访问失败。跨源域资源共享CORS(Cross-Origin Resource Sharing)允许Web应用服务器进行跨域访问控制。本文介绍如何在ASM的Virtualservice中配置corsPolicy,实现跨域资源共享。

跨源域资源共享CORS介绍

出于安全性考虑,浏览器会限制页面脚本内发起的跨源HTTP请求,例如在使用XMLHttpRequest和Fetch API遵循同源策略,使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。

跨域资源共享CORS是一种基于HTTP头的机制,该机制允许服务器标示除了它自己以外的其它域,协议和端口,使得浏览器可以访问加载这些资源。

跨域资源共享CORS的验证机制分两种模式:简单请求和预先请求。
  • 简单请求模式:

    浏览器直接发送跨域请求,并在请求头中携带Origin的头,表明这是一个跨域的请求。服务器端接到请求后,会根据自己的跨域规则,通过Access-Control-Allow-Origin和Access-Control-Allow-Methods响应头,来返回验证结果。

  • 预先请求模式:

    浏览器会先发送Preflighted requests(预先验证请求),Preflighted requests是一个OPTION请求,用于询问要被跨域访问的服务器,是否允许当前域名下的页面发送跨域的请求。在得到服务器的跨域授权后才能发送真正的HTTP请求。

    OPTIONS请求头部中会包含以下头部:Origin、Access-Control-Request-Method、Access-Control-Request-Headers。服务器收到OPTIONS请求后,设置Access-Control-Allow-Origin、Access-Control-Allow-Method、Access-Control-Allow-Headers、Access-Control-Max-Age头部与浏览器沟通来判断是否允许这个请求。如果Preflighted requests验证通过,浏览器才会发送真正的跨域请求。

当请求同时满足下面三个条件时,CORS验证机制会使用简单请求模式进行处理,否则CORS验证机制会使用预先请求模式进行处理。
  • 请求方法是下列之一:

    GET、HEAD、POST

  • 请求头中的Content-Type请求头的值是下列之一:

    ext/plain、application/x-www-form-urlencoded、multipart/form-data

  • Fetch规范定义了CORS安全头的集合,安全头的集合是下列之一:

    Accept、Accept-Language、Content-Language、Content-Type(需要注意额外的限制)

在VirtualService中配置corsPolicy

整个CORS通信过程都是浏览器自动完成,您需要在对应服务的VirtualService中添加corsPolicy字段,使服务允许跨域请求,从而实现跨域通信。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings-route
spec:
  hosts:
  - ratings.prod.svc.cluster.local
  http:
  - route:
    - destination:
        host: ratings.prod.svc.cluster.local
        subset: v1
    corsPolicy:
      allowOrigins:
      - exact: https://example.com
#     - regex: *     #支持regex
      allowMethods:
      - POST
      - GET
      allowCredentials: false
      allowHeaders:
      - X-Foo-Bar
      maxAge: "24h"
参数 说明
allowOrigins 允许请求服务的来源,允许带哪些Origin地址的请求,支持regex匹配。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。
allowMethods 允许请求服务的方法,实际请求所允许使用的HTTP方法。
allowHeaders 允许请求服务的标头,用于预检请求的响应。其指明了实际请求中允许携带的首部字段。
exposeHeaders 公开请求服务的标头,让服务器把允许浏览器访问的头放入白名单。
maxAge 最大浏览器缓存时间,指定了浏览器能够缓存preflight请求结果的时间。
allowCredentials 允许请求服务的凭证,符合要求的凭证才能请求服务。