同源策略
就是瀏覽器規(guī)定的只有相同的協(xié)議,相同的域名,相同的端口,滿足以上條件才能讀取對(duì)方的資源,否則不能。
什么是跨域?跨域有幾種實(shí)現(xiàn)形式
跨域:就是通過(guò)一些處理,可以讓不同的域名之間可以相互讀取資源
跨域有4種實(shí)現(xiàn)形式:
1.JSONP:html可以加載另一個(gè)域名的js文件,然后我們可以利用這個(gè)功能,后端可以將數(shù)據(jù)整合成為js格式的字符串讓前端加載,加載好后,前端通過(guò)函數(shù)將其數(shù)據(jù)華為己用。
2.COSR:跨域資源共享(Cross-Origin Resource Sharing),在后端設(shè)置cosr屬性,res.header(''Access-Content-Allow-Origin","同意訪問(wèn)的url"),相應(yīng)的url就能訪問(wèn)這個(gè)后端服務(wù)器了。
3.降域:2者要設(shè)置document.domain='"' 訪問(wèn)的前后都要降域并且2者都要有同一個(gè)基礎(chǔ)域名。
4.passMassage:window下的一個(gè)方法,window.passMessage(值,傳遞的地址)
JSONP 的原理
html可以加載另一個(gè)域名的js文件,然后我們可以利用這個(gè)功能,后端可以將數(shù)據(jù)整合成為js格式的字符串讓前端加載,加載好后,前端通過(guò)函數(shù)將其數(shù)據(jù)華為己用。
例如
$('.change').addEventListener('click', function(){ var script = document.createElement('script'); script.src = 'http://127.0.0.1/getNews?callback=appendHtml'; document.head.appendChild(script); document.head.removeChild(script); }) function appendHtml(news){ var html = ""; for(var i = 0; i<news.length;i++){ html = '<li>'+news[i]+'</li>' } $(.news).innerHTML = html; }
以上是前端,下面是后端
app.get("getNews",function(){ var new = [x,x,x]; var data = []; for (var i = 0; i<3; i++){ var index = parseInt(Math.random()*news.length); data.push(new[index]); news.splice(index,1); } var cb = req.query.callback; if(req.query.callback){ res.send(cb + '('+ JSON.stringify(data) + ')') }else{res.send(data)} })
CORS是什么
跨域資源共享(Cross-Origin Resource Sharing),分為簡(jiǎn)單請(qǐng)求和復(fù)雜請(qǐng)求,簡(jiǎn)單請(qǐng)求在后端設(shè)置cosr屬性,res.header(''Access-Content-Allow-Origin","同意訪問(wèn)的url"),相應(yīng)的url就能訪問(wèn)這個(gè)后端服務(wù)器了。
復(fù)雜請(qǐng)求:
表面上看起來(lái)和簡(jiǎn)單請(qǐng)求使用上差不多,但實(shí)際上瀏覽器發(fā)送了不止一個(gè)請(qǐng)求。其中最先發(fā)送的是一種"預(yù)請(qǐng)求",此時(shí)作為服務(wù)端,也需要返回"預(yù)回應(yīng)"作為響應(yīng)。預(yù)請(qǐng)求實(shí)際上是對(duì)服務(wù)端的一種權(quán)限請(qǐng)求,只有當(dāng)預(yù)請(qǐng)求成功返回,實(shí)際請(qǐng)求才開(kāi)始執(zhí)行。預(yù)請(qǐng)求以O(shè)PTIONS形式發(fā)送,當(dāng)中同樣包含域,并且還包含了兩項(xiàng)CORS特有的內(nèi)容:
Access-Control-Request-Method – 該項(xiàng)內(nèi)容是實(shí)際請(qǐng)求的種類,可以是GET、POST之類的簡(jiǎn)單請(qǐng)求,也可以是PUT、DELETE等等。
Access-Control-Request-Headers– 該項(xiàng)是一個(gè)以逗號(hào)分隔的列表,當(dāng)中是復(fù)雜請(qǐng)求所使用的頭部。
顯而易見(jiàn),這個(gè)預(yù)請(qǐng)求實(shí)際上就是在為之后的實(shí)際請(qǐng)求發(fā)送一個(gè)權(quán)限請(qǐng)求,在預(yù)回應(yīng)返回的內(nèi)容當(dāng)中,服務(wù)端應(yīng)當(dāng)對(duì)這兩項(xiàng)進(jìn)行回復(fù),以讓瀏覽器確定請(qǐng)求是否能夠成功完成。
復(fù)雜請(qǐng)求的部分響應(yīng)頭及解釋如下:
Access-Control-Allow-Origin(必含) – 和簡(jiǎn)單請(qǐng)求一樣的,必須包含一個(gè)域。
Access-Control-Allow-Methods(必含) – 這是對(duì)預(yù)請(qǐng)求當(dāng)中Access-Control-Request-Method的回復(fù),這一回復(fù)將是一個(gè)以逗號(hào)分隔的列表。盡管客戶端或許只請(qǐng)求某一方法,但服務(wù)端仍然可以返回所有允許的方法,以便客戶端將其緩存。
Access-Control-Allow-Headers(當(dāng)預(yù)請(qǐng)求中包含Access-Control-Request-Headers時(shí)必須包含) – 這是對(duì)預(yù)請(qǐng)求當(dāng)中Access-Control-Request-Headers的回復(fù),和上面一樣是以逗號(hào)分隔的列表,可以返回所有支持的頭部。這里在實(shí)際使用中有遇到,所有支持的頭部一時(shí)可能不能完全寫出來(lái),而又不想在這一層做過(guò)多的判斷,沒(méi)關(guān)系,事實(shí)上通過(guò)request的header可以直接取到Access-Control-Request-Headers,直接把對(duì)應(yīng)的value設(shè)置到Access-Control-Allow-Headers即可。
Access-Control-Allow-Credentials(可選) – 和簡(jiǎn)單請(qǐng)求當(dāng)中作用相同。
Access-Control-Max-Age(可選) – 以秒為單位的緩存時(shí)間。預(yù)請(qǐng)求的的發(fā)送并非免費(fèi)午餐,允許時(shí)應(yīng)當(dāng)盡可能緩存。
一旦預(yù)回應(yīng)如期而至,所請(qǐng)求的權(quán)限也都已滿足,則實(shí)際請(qǐng)求開(kāi)始發(fā)送。
通caniuse.com得知,目前大部分Modern瀏覽器已經(jīng)支持完整的CORS,但I(xiàn)E直到IE11才完美支持,所以對(duì)于PC網(wǎng)站,還是建議采用其他解決方案,如果僅僅是移動(dòng)端網(wǎng)站,大可放心使用。
根據(jù)視頻里的講解演示三種以上跨域的解決方式
1.JSONP:題目三已有
2.cors:http://js.jirengu.com/mucayijibe/1/edit?html,js,output
3.降域:http://js.jirengu.com/tapafaneni/1/edit
4.passMassage:http://js.jirengu.com/jawufeyile/1/edit