當一個用戶端去訪問另一個不同網域名稱或者同網域名稱不同連接埠的服務時,就會發出跨域請求。如果此時該服務不允許其進行跨域資源訪問,就會因為跨域問題而導致訪問失敗。跨源域資源共用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
欄位,使服務允許跨域請求,從而實現跨域通訊。
參數 | 說明 |
allowOrigins | 允許請求服務的來源,允許帶哪些Origin地址的請求,支援regex匹配。對於不需要攜帶身份憑證的請求,伺服器可以指定該欄位的值為萬用字元,表示允許來自所有域的請求。 |
allowMethods | 允許請求服務的方法,實際請求所允許使用的HTTP方法。 |
allowHeaders | 允許請求服務的標題,用於預檢請求的響應。其指明了實際請求中允許攜帶的首部欄位。 |
exposeHeaders | 公開請求服務的標題,讓伺服器把允許瀏覽器訪問的頭放入白名單。 |
maxAge | 最大瀏覽器緩衝時間,指定了瀏覽器能夠緩衝preflight請求結果的時間。 |
allowCredentials | 允許請求服務的憑證,符合要求的憑證才能請求服務。 |
跨域訪問最佳實務
準備工作
已添加叢集到ASM執行個體。具體操作,請參見添加叢集到ASM執行個體。
已建立default和foo命名空間,並為命名空間開啟自動注入。具體操作,請參見管理全域命名空間。
步驟一:部署應用
部署後端應用。
使用以下內容,建立details.yaml 檔案。
執行以下命令,在default命名空間部署details應用。
kubectl apply -f details.yaml -n default
部署前端應用。
使用以下內容,建立istio-cors-demo.yaml 檔案。
執行以下命令,在foo命名空間部署istio-cors-demo應用。
kubectl apply -f istio-cors-demo.yaml -n foo
步驟二:建立ASM網關
登入ASM控制台,在左側導覽列,選擇 。
在網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇 。
在入口網關頁面,單擊建立。
在建立頁面,設定名稱為ingressgateway,選擇部署叢集,設定負載平衡CLB類型為公網訪問,在建立負載平衡CLB下選擇負載平衡規格,其他參數採用預設設定,然後單擊建立。
步驟三:建立路由規則
建立後端應用的路由規則。
建立網關規則,綁定details應用和ingressgateway網關。
登入ASM控制台,在左側導覽列,選擇 。
在網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇
。在網關規則頁面,單擊使用YAML建立。
在建立頁面,設定命名空間為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
建立虛擬服務。
在網格詳情頁面左側導覽列選擇
,然後在右側頁面單擊使用YAML建立。在建立頁面,設定命名空間為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
訪問後端應用。
擷取ingressgateway網關的IP地址,具體操作,請參見建立入口網關。
在瀏覽器地址欄中輸入http://<ingressgateway網關的IP>/details/2 。
返回以上頁面,表明訪問後端應用details成功。
建立前端應用的路由規則。
建立網關規則。
建立網關規則,綁定istio-cors-demo應用和ingressgateway2網關。
在網格詳情頁面左側導覽列,選擇
,然後在網關規則頁面,單擊使用YAML建立。在建立頁面,設定命名空間為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
建立虛擬服務。
在網格詳情頁面左側導覽列,選擇
,然後在虛擬服務頁面,單擊使用YAML建立。在建立版面設定命名空間為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
使用前端應用訪問後端應用。
擷取ingressgateway2網關的IP地址,具體操作,請參見建立入口網關。
在Google瀏覽器地址欄,輸入http://<ingressgateway2網關的IP地址>。
在URL文字框,輸入http://<ingressgateway網關的IP地址>/details/2 ,單擊Send。
在Google瀏覽器右上方,單擊表徵圖,選擇 。
由於前端istio-cors-demo應用訪問後端details應用需要跨域,訪問會失敗,因此出現以上報錯。
步驟四:配置跨域訪問
登入ASM控制台,在左側導覽列,選擇 。
在網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇 。
在虛擬服務頁面,單擊bookinfo右側操作列下的查看YAML。
在編輯對話方塊的http參數下,添加以下跨網域設定,然後單擊確定。
- corsPolicy: allowCredentials: false allowMethods: - POST - GET allowOrigins: - prefix: 'http://<ingressgateway2網關的IP>' maxAge: 24h
步驟五:驗證跨域訪問是否成功
在Google瀏覽器地址欄,輸入http://<ingressgateway2網關的IP地址>。
在URL文字框,輸入http://<ingressgateway網關的IP地址>/details/2 ,單擊Send。
返回以上頁面,表明前端istio-cors-demo應用訪問後端details應用成功,跨域訪問成功。