實際跨域問題及其解決方案
1.課題:ajax實現跨域訪問
2.背景:
1.畫面伺服器:192.168.196.6 → tomcat服務
2.js模板伺服器:192.168.196.8 → nginx服務
3.畫面服務需跨域請求js資源
3.錯誤:
過程中經過了幾次配置,出現過以下錯誤
1.No `Access-Control-Allow-Origin` header is present on the requested resource,The response had HTTP status code 404
2.No `Access-Control-Allow-Origin` header is present on the requested resource,The response had HTTP status code 405
4.解決:
nginx服務配置(nginx.conf):
location xxx {
alias xxx;
--允許GET請求,GET請求時返回以下頭資訊
if ($request_method = `GET`) {
add_header `Access-Control-Allow-Origin` `*`;
add_header `Access-Control-Allow-Headers` `X-Requested-With`;
}
--允許預檢請求,預檢請求時返回以下頭資訊
if ($request_method = `OPTIONS`) {
add_header `Access-Control-Allow-Origin` `*`;
add_header `Access-Control-Allow-Methods` `GET, POST, OPTIONS`;
add_header `Access-Control-Allow-Headers` `X-Requested-With`;
add_header `Content-Length` 0;
return 204;
}
}
分析:
1.我的跨域請求是GET方法,所以只配置GET就好用了。
2.我的請求是非簡單請求,所以需要給預檢請求(OPTIONS)配置介面。
學習與總結
CORS理解
CORS是一個W3C標準,全稱是Cross-origin resource sharing(跨域資源共享)。
CORS需要瀏覽器和伺服器同時支援。目前,所有瀏覽器都支援該功能,IE瀏覽器不能低於IE10。
因此,實現CORS通訊的關鍵是伺服器。只要伺服器實現了CORS介面,就可以跨源通訊。
CORS分類
瀏覽器將CORS請求分成兩類:
- 簡單請求(simple request)
- 非簡單請求(not-so-simple request)
簡單請求
-
滿足以下兩個條件就是簡單請求
- (1) 請求方法是以下三種方法之一: HEAD,GET,POST
-
(2) HTTP的頭資訊不超出以下幾種欄位:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
-
請求過程
1.瀏覽器直接發出CORS請求。跟普通請求相比,增加一個Origin欄位。GET /cors HTTP/1.1 Origin: http://192.168.196.160 Host: xxx Accept-Language: xxx Connection: xxx User-Agent: xxx
2.如果Origin指定的域名在許可範圍內,伺服器返回的響應,會多出頭資訊欄位Access-Control-Allow-Origin(也可能多出其他可選欄位)
Access-Control-Allow-Origin: http://192.168.196.160 //或者是 *,表示接受任意域名的請求。 Content-Type: text/html; charset=utf-8
非簡單請求
- 簡單請求以外就是非簡單請求。非簡單請求就是對伺服器有特殊的請求,比如請求方法是PUT或DELETE,或者Content-Type欄位型別是application/json。
-
非簡單請求會在請求之前增加”預檢”請求(prelight)。
-
預檢請求
- 瀏覽器詢問伺服器,當前網頁所在域名是否在伺服器訪問許可名單(Origin),是否允許該請求方法(Access-Control-Request-Method)和頭資訊欄位(Access-Control-Request-Headers)。
-
伺服器得到預檢請求後,檢查Origin,Access-Control-Request-Method,Access-Control-Request-Headers欄位,
-
如果確認允許跨域請求,就可以HTTP回應中帶上這三個頭資訊,如下
Access-Control-Allow-Origin: 請求源域名或者* Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-Custom-Header
-
如果不允許跨域請求,伺服器返回正常相應,但是不帶cors頭資訊欄位,瀏覽器就會觸發錯誤如下
XMLHttpRequest cannot load 請求源域名 Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
-
-
- 預檢請求通過後,以後每次瀏覽器的正常cors請求都跟簡單請求一樣。請求頭資訊會帶著origin,伺服器的響應也都會有頭資訊欄位Access-Control-Allow-Origin。(參考簡單請求)