全部產品
Search
文件中心

Alibaba Cloud Service Mesh:在ASM中實現跨域訪問

更新時間:Jun 30, 2024

當一個用戶端去訪問另一個不同網域名稱或者同網域名稱不同連接埠的服務時,就會發出跨域請求。如果此時該服務不允許其進行跨域資源訪問,就會因為跨域問題而導致訪問失敗。跨源域資源共用CORS(Cross-Origin Resource Sharing)允許Web應用伺服器進行跨域存取控制。本文介紹如何在ASM的Virtualservice中配置corsPolicy,實現跨域訪問。

跨源域資源共用CORS介紹

瀏覽器會限制頁面指令碼內發起的跨源HTTP請求以提高安全性,對於需要跨域訪問的情境,ASM提供了跨源域資源共用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要求標頭的值是下列之一:

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

  • Fetch規範定義了CORS安全頭的集合,安全頭的集合是下列之一:

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

在VirtualService中配置corsPolicy

整個CORS通訊過程都是瀏覽器自動完成,您需要在對應服務的VirtualService中添加corsPolicy欄位,使服務允許跨域請求,從而實現跨域通訊。

展開查看VirtualService樣本

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

允許請求服務的憑證,符合要求的憑證才能請求服務。

跨域訪問最佳實務

準備工作

步驟一:部署應用

  1. 部署後端應用。

    1. 擷取叢集KubeConfig並通過kubectl工具串連叢集

    2. 使用以下內容,建立details.yaml 檔案。

      展開查看details.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: details
        labels:
          app: details
          service: details
      spec:
        ports:
        - port: 9080
          name: http
        selector:
          app: details
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: bookinfo-details
        labels:
          account: details
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: details-v1
        labels:
          app: details
          version: v1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: details
            version: v1
        template:
          metadata:
            labels:
              app: details
              version: v1
          spec:
            serviceAccountName: bookinfo-details
            containers:
            - name: details
              image: docker.io/istio/examples-bookinfo-details-v1:1.16.4
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 9080
              securityContext:
                runAsUser: 1000
    3. 執行以下命令,在default命名空間部署details應用。

      kubectl apply -f details.yaml -n default
  2. 部署前端應用。

    1. 使用以下內容,建立istio-cors-demo.yaml 檔案。

      展開查看istio-cors-demo.yaml

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: istio-cors-demo
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: istio-cors-demo
        labels:
          app: istio-cors-demo
          service: istio-cors-demo
      spec:
        ports:
          - name: http
            port: 8000
            targetPort: 80
        selector:
          app: istio-cors-demo
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: istio-cors-demo
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: istio-cors-demo
            version: v1
        template:
          metadata:
            labels:
              app: istio-cors-demo
              version: v1
          spec:
            serviceAccountName: istio-cors-demo
            containers:
              - image: registry.cn-hangzhou.aliyuncs.com/build-test/istio-cors-demo:v1.0-g8e215f6-aliyun
                imagePullPolicy: IfNotPresent
                name: istio-cors-demo
                ports:
                  - containerPort: 80
    2. 執行以下命令,在foo命名空間部署istio-cors-demo應用。

      kubectl apply -f istio-cors-demo.yaml -n foo 

步驟二:建立ASM網關

  1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

  2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇ASM網關 > 入口網關

  3. 入口網關頁面,單擊建立

  4. 建立頁面,設定名稱ingressgateway,選擇部署叢集,設定負載平衡CLB類型公網訪問,在建立負載平衡CLB下選擇負載平衡規格,其他參數採用預設設定,然後單擊建立

  5. 重複步驟3步驟4,建立名為ingressgateway2的網關。

步驟三:建立路由規則

  1. 建立後端應用的路由規則。

    1. 建立網關規則,綁定details應用和ingressgateway網關。

      1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

      2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇ASM網關 > 網關規則

      3. 網關規則頁面,單擊使用YAML建立

      4. 建立頁面,設定命名空間default,選擇任意情境模版,將YAML文字框中的內容替換為以下內容,然後單擊建立

        apiVersion: networking.istio.io/v1beta1
        kind: Gateway
        metadata:
          name: bookinfo-gateway
          namespace: default
        spec:
          selector:
            istio: ingressgateway
          servers:
            - hosts:
                - '*'
              port:
                name: http
                number: 80
                protocol: HTTP
                                           
    2. 建立虛擬服務。

      1. 在網格詳情頁面左側導覽列選擇流量管理中心 > 虛擬服務,然後在右側頁面單擊使用YAML建立

      2. 建立頁面,設定命名空間default,選擇任意情境模版,將YAML文字框中的內容替換為以下內容,然後單擊建立

        apiVersion: networking.istio.io/v1beta1
        kind: VirtualService
        metadata:
          name: bookinfo
          namespace: default
        spec:
          gateways:
            - bookinfo-gateway
          hosts:
            - '*'
          http:
            - match:
                - uri:
                    prefix: /details
              route:
                - destination:
                    host: details
                    port:
                      number: 9080
                                                
    3. 訪問後端應用。

      1. 擷取ingressgateway網關的IP地址,具體操作,請參見建立入口網關

      2. 在瀏覽器地址欄中輸入http://<ingressgateway網關的IP>/details/2 detail

        返回以上頁面,表明訪問後端應用details成功。

  2. 建立前端應用的路由規則。

    1. 建立網關規則。

      建立網關規則,綁定istio-cors-demo應用和ingressgateway2網關。

      1. 在網格詳情頁面左側導覽列,選擇ASM網關 > 網關規則,然後在網關規則頁面,單擊使用YAML建立

      2. 建立頁面,設定命名空間foo,選擇任意情境模版,將YAML文字框中的內容替換為以下內容,然後單擊建立

        apiVersion: networking.istio.io/v1beta1
        kind: Gateway
        metadata:
          name: istio-cors-demo-gateway
          namespace: foo
        spec:
          selector:
            istio: ingressgateway2
          servers:
            - hosts:
                - '*'
              port:
                name: http
                number: 80
                protocol: HTTP
    2. 建立虛擬服務。

      1. 在網格詳情頁面左側導覽列,選擇流量管理中心 > 虛擬服務,然後在虛擬服務頁面,單擊使用YAML建立

      2. 建立版面設定命名空間foo,選擇任意情境模版,將YAML文字框中的內容替換為以下內容,然後單擊建立

        apiVersion: networking.istio.io/v1beta1
        kind: VirtualService
        metadata:
          name: istio-cors-demo
          namespace: foo
        spec:
          gateways:
            - istio-cors-demo-gateway
          hosts:
            - '*'
          http:
            - route:
                - destination:
                    host: istio-cors-demo
                    port:
                      number: 8000
  3. 使用前端應用訪問後端應用。

    1. 擷取ingressgateway2網關的IP地址,具體操作,請參見建立入口網關

    2. 在Google瀏覽器地址欄,輸入http://<ingressgateway2網關的IP地址>

    3. 在URL文字框,輸入http://<ingressgateway網關的IP地址>/details/2 ,單擊Send

      URL

    4. 在Google瀏覽器右上方,單擊設定表徵圖,選擇更多工具 > 開發人員工具

      報錯

      由於前端istio-cors-demo應用訪問後端details應用需要跨域,訪問會失敗,因此出現以上報錯。

步驟四:配置跨域訪問

  1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

  2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇流量管理中心 > 虛擬服務

  3. 虛擬服務頁面,單擊bookinfo右側操作列下的查看YAML

  4. 編輯對話方塊的http參數下,添加以下跨網域設定,然後單擊確定

    - corsPolicy:
        allowCredentials: false
        allowMethods:
          - POST
          - GET
        allowOrigins:
          - prefix: 'http://<ingressgateway2網關的IP>'
        maxAge: 24h

    代碼

步驟五:驗證跨域訪問是否成功

  1. 在Google瀏覽器地址欄,輸入http://<ingressgateway2網關的IP地址>

  2. 在URL文字框,輸入http://<ingressgateway網關的IP地址>/details/2 ,單擊Send

    訪問成功

    返回以上頁面,表明前端istio-cors-demo應用訪問後端details應用成功,跨域訪問成功。