跨域:
官方解釋:跨域是指瀏覽器不能執行其他網站的指令碼。它是有瀏覽器的同源策略造成的,是瀏覽器施加的安全限制。
從這裡面我們可以提取到第一個點-->“跨域問題是瀏覽器產生的”
複製程式碼
跨域,又稱跨域名訪問。其中又分為:二級域名跨域、多級 域名跨域、埠號跨域以及協議跨域。
下面說明這幾種跨域,假如一網站是 http://www.abc.com,那麼該網站訪問其他資源的路徑可能是以下幾種:
1、http://abc.com 二級域名跨域
2、http://www.abc.cn 主域名跨域
3、http://www.def.com 主域名跨域
4、https://www.abc.com 協議跨域複製程式碼
解決跨域的方法:
一、jsonp 跨域
jsonp跨域是利用,在瀏覽器當中,img標籤的src、以及script標籤的src、以及link標籤的href不受瀏覽器同源政策的限制。繞過ajax去請求資料。既然如此,我們就可以利用動態的建立script標籤的方式,去跨域請求資料了。
這裡我使用node做示例,那麼我就利用express來建立一個jsonp資料,之後就來請求這個資料即可
app.get('/jsonp', (req, res, next) => {
res.jsonp({
data: 'this is a jsonp data'
})
})複製程式碼
既然jsonp是利用script標籤去請求資料,那麼我們就需要動態建立script標籤
第一步:定義處理函式,用來處理接收到的資料
function getData(res) {
console.log(res)
}複製程式碼
第二步:建立script標籤,去請求資料
let jsonp = document.createElement('script')
jsonp.src = 'http://localhost:3000/jsonp?callback=getData'複製程式碼
這裡jsonp預設使用callback作為請求引數
在這之後資料會被列印出來。
jsonp的優勢:相容性比較好(幾乎所有瀏覽器都支援script標籤)
jsonp的劣勢:jsonp只支援get請求
二、cors跨域
CORS需要瀏覽器和伺服器同時支援,目前幾乎所有瀏覽器都支援CORS,IE不能低於IE10。整個CORS跨域的過程,前端都是瀏覽器自動完成的,瀏覽器一旦發現ajax請求跨域資源,就會自動新增一些附加的頭資訊,有時還會多一次試探性的OPTIONS請求。
CORS又分為簡單請求和非簡單請求
① 簡單請求:
要同時滿足以下幾個條件:
1、請求方式是 HEAD、GET、POST其中的一個
2、http的請求頭不超出以下幾種資訊:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type
3、Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
簡單請求時瀏覽器會自動帶上一個請求頭" Origin: 客戶端域名 ”
當瀏覽器接收到伺服器返回的響應時,會對響應頭進行分析。如果 存在 Access-Control-Allow-Origin:“客戶端域名”;那麼瀏覽器就會把請求到的資料返回給ajax物件,否則就會觸發ajax的onerror事件,丟擲一個錯誤異常
② 非簡單請求
對於非簡單請求一般分為以下步驟
第一步:
瀏覽器先發出一個options的請求。並且包含一些頭部資訊:
Origin:客戶端域名Access-Control-Request-Headers: content-type (表明客戶端傳送的請求頭資料)Access-Control-Request-Method: POST (表明客戶端傳送的請求型別)複製程式碼
第二步:
伺服器返回options請求
Access-Control-Allow-Origin:允許跨域的域名(可以是指定域名,也可以是全域名“*”)Access-Control-Allow-Headers: “與客戶端對應”Access-Control-Allow-Method: 與客戶端的對應或者大於客戶端複製程式碼
第三步:
客戶端檢查options請求的響應頭。如
Access-Control-Allow-Origin:允許跨域的域名Access-Control-Allow-Headers: “與客戶端對應”Access-Control-Allow-Method: 與客戶端的對應或者大於客戶端複製程式碼
如果伺服器的響應頭與瀏覽器的請求頭對應了,瀏覽器會正式發出請求,伺服器對請求做出響應,並帶上之前的請求頭完成跨域。
不過雖然上面的 對響應頭的設定已經可以實現跨域了不過會造成session的丟失,對此我們需要設定另一個請求頭引數Access-Control-Allow-Credentials = true,在預設false情況下客戶端是不會攜帶cookies到伺服器的。
session丟失的解決:
在響應頭裡邊,指定唯一的允許跨域的域名。服務端在響應頭裡邊。指定Access-Control-Allow-Credentials:true,以及客戶端的ajax物件,必須指withCredentials: true;
更好的瞭解cors跨域的同學可以看看阮一峰老師的《跨域資源共享 CORS 詳解》
下面是express實現cors跨域,瀏覽器端的請求頭瀏覽器會自動新增
router.options('/getCorsData',(req,res)=>{
res.header('Access-Control-Allow-Origin','*') //設定允許訪問的域名 * 代表所有
res.header('Access-Control-Allow-Headers','content-type')
res.header('Access-Control-Allow-Method','OPTIONS,POST,PUT')
res.header('Access-Control-Allow-Credentials','true')
res.send(200)
})
複製程式碼
三、代理跨域
代理跨域的道理很簡單,既然跨域是因為瀏覽器的同源策略引起的,那麼非同源資源不交給瀏覽器去直接請求,而是讓同源伺服器去請求再返回給瀏覽器
express程式碼示例:
app.get('/getdata', (req, res) => {
request('http://localhost:3000/getCors', (err, response, body) => {
res.json(response)
})
})複製程式碼
以上程式碼是我是開了兩個伺服器模擬的一個 3001 埠另一個是3000埠,屬於埠跨域,在3001的頁面中去訪問getdata時伺服器向3000埠請求資料,並把資料返回給頁面,完成跨域。
但一般我們都是去使用中介軟體去完成代理跨域。比如 http-proxy-middleware,有興趣的可以去github中檢視使用方法。
總結
知識在於積累,生命在於折騰,有錯誤的請留言指出,批評使我進步