JSONP_跨域

什么是同源策略

同源政策(same-origin policy)是指同域名(或ip),同端口鼻由,同協(xié)議視為同一個域蕉世,同域內(nèi)的腳本只能讀寫本域內(nèi)的資源,而無法訪問其它域的資源奸例,這種安全限制稱為同源策略查吊。當(dāng)一個瀏覽器的兩個tab頁中分別打開來百度和谷歌的頁面當(dāng)瀏覽器的百度tab頁執(zhí)行一個腳本的時候會檢查這個腳本是屬于哪個頁面的湖蜕,即檢查是否同源昭抒,只有和百度同源的腳本才會被執(zhí)行。如果非同源盗迟,那么在請求數(shù)據(jù)時罚缕,瀏覽器會在控制臺中報一個異常,提示拒絕訪問怎静。
同域指的是喂饥?
同協(xié)議:如都是http或者h(yuǎn)ttps
同域名:如都是http://baidu.com/ahttp://baidu.com/b
同端口:如都是8080端口
如果不是同源的员帮,會受到三種限制:

1.Cookie捞高、LocalStorage 和 IndexDB 無法讀取渣锦。
2. DOM 無法獲得袋毙。
3.AJAX 請求不能發(fā)送。

什么是跨域胀溺?跨域有幾種實現(xiàn)形式

跨域
跨域是指從一個域名的網(wǎng)頁去請求另一個域名的資源仓坞。比如從百度頁面去請求谷歌的資源腰吟。跨域的嚴(yán)格一點的定義是:只要 協(xié)議嫉称,域名织阅,端口有任何一個的不同始藕,就被當(dāng)作是跨域。
跨域有幾種實現(xiàn)形式
一.JSONP
JSONP是服務(wù)器與客戶端跨源通信的常用方法江耀。最大特點就是簡單適用祥国,兼容性好。主要利用html中script標(biāo)簽可以引入其他域的js文件啊犬,利用這個特性可以實現(xiàn)跨域訪問接口觉至,需要后端的支持睡腿。實現(xiàn)步驟:
1.定義數(shù)據(jù)處理函數(shù)fun:
2.網(wǎng)頁通過添加一個<script>元素席怪,src的地址執(zhí)行后端接口最后加個參數(shù)callback=fun,向服務(wù)器請求JSON數(shù)據(jù)碉纺,這種做法不受同源政策限制骨田;
3.服務(wù)器收到請求后疫赎,將數(shù)據(jù)放在fun回調(diào)函數(shù)里傳回來,輸出fun(data):
4.fun(data)會放到script標(biāo)簽作為js執(zhí)行捧搞,此時會調(diào)用fun(data),將data作為參數(shù)胎撇。
定義處理函數(shù)

  function foo(data){
      console.log(data.ip)
    }

網(wǎng)頁動態(tài)插入<script>元素殖氏,由它向跨源網(wǎng)址發(fā)出請求。

function addScriptTag(src) {
  var script = document.createElement('script');
  script.src = src;
  document.head.appendChild(script);
  document.head.removeChild(script);
}
window.onload = function () { 
  addScriptTag('http://example.com/ip?callback=foo');
}

服務(wù)器收到這個請求以后爵憎,會將數(shù)據(jù)放在回調(diào)函數(shù)的參數(shù)位置返回

foo({
  "ip":"10.64.25.83"
})

由于<script>元素請求的腳本宝鼓,直接作為代碼運行愚铡。這時,只要瀏覽器定義了foo函數(shù)碍舍,該函數(shù)就會立即調(diào)用邑雅。作為參數(shù)的JSON數(shù)據(jù)被視為JavaScript對象淮野,而不是字符串,因此避免了使用JSON.parse的步驟录煤。
缺點:
1.只能通過GET方式請求妈踊,參數(shù)長度有限制,安全性比較差
2.需要后端的支持
二.CORS
CORS全稱是"跨域資源共享"(Cross-origin resource sharing)歪泳。
它允許瀏覽器向跨源服務(wù)器呐伞,發(fā)出XMLHttpRequest請求慎式。支持現(xiàn)代瀏覽器瘪吏,IE10以上瀏覽器。CORS需要瀏覽器和服務(wù)器的支持蕾盯,因此级遭,實現(xiàn)CORS通信的關(guān)鍵是服務(wù)器渺尘。只要服務(wù)器實現(xiàn)了CORS接口,就可以跨源通信掠兄。
當(dāng)CORS請求滿足下面的條件時
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.當(dāng)使用XMLHttpRequest()發(fā)送請求的時候侈贷,瀏覽器發(fā)現(xiàn)該請求不符合同源策略等脂,會給該請求的頭部信息添加一個origin字段上遥,Origin字段用來說明,本次請求來自哪個源辣恋,服務(wù)器根據(jù)這個值模软,決定是否同意這次請求。
如果Origin指定的源携狭,不被服務(wù)器允許逛腿,服務(wù)器也會返回正常的HTTP響應(yīng)鲫剿,瀏覽器發(fā)現(xiàn)響應(yīng)頭沒有包含origin字段,就拋出錯誤,被onerror回調(diào)函數(shù)捕獲政冻,這種錯誤狀態(tài)碼無法識別。
2.如果指定的源明场,被服務(wù)器允許苦锨,服務(wù)器返回響應(yīng)信息的響應(yīng)頭會包含origin的信息,如下:

Paste_Image.png

三.document.domain(也就是降域)
document.domain用于主域相同子域不同的場景
降域的設(shè)置也是有限制的拉庶,只能把document.domain氏仗,設(shè)置成自身或者更高一級的域夺鲜,且主域必須相同币励,如:a.b.test.com中的某個文檔的域可以設(shè)置成a.b.test.com、b.test.com流炕、test.com搁进。但是不可以設(shè)置成.com或者c.a.b.test.com或者baidu.com饼问,因為baidu.com主域和當(dāng)前域不同了。
使用方法
a頁面中加入document.domain = ‘test.com’;
b頁面中加入document.domain = ‘test.com’;
a.index.html

<div class="ct">
  <h1>使用降域?qū)崿F(xiàn)跨域</h1>
  <div class="main">
    <input type="text" placeholder="http://a.test.com:8080/a.html">
  </div>
  <iframe src="http://b.test.com:8080/b.html" frameborder="0" ></iframe>
</div>
<script>
document.querySelector('.main input').addEventListener('input', function(){
  console.log(this.value);
  window.frames[0].document.querySelector('input').value = this.value;
})
document.domain = "test.com"

b.index.html

<div>
  <input id="input" type="text"  placeholder="http://b.test.com:8080/b.html">
</div>
<script>
   document.querySelector('#input').addEventListener('input', function(){
    window.parent.document.querySelector('input').value = this.value;
})
document.domain = 'test.com';
</script>
</html>

四峻堰,postMessage
postMessage是html5新增的方法捐名,可以實現(xiàn)跨文本檔镶蹋、多窗口赏半、跨域消息傳遞。該方法可以通過綁定window的message事件來監(jiān)聽發(fā)送跨文檔消息傳輸內(nèi)容拂酣。postMessage(data,origin)方法接受兩個參數(shù):
1.data:要傳遞的數(shù)據(jù)婶熬。
2.origin:字符串參數(shù),指明目標(biāo)窗口的源虽另,協(xié)議+主機+端口號[+URL]性含,URL會被忽略,所以可以不寫叠萍,這個參數(shù)是為了安全考慮postMessage()方法只會將message傳遞給指定窗口苛谷,如果設(shè)置為"*",這樣可以傳遞給任意窗口腹殿。
http://a.test.com/a.html

<div class="main">
        <input type="text" placeholder="http://a.test.com/a.html">
    </div>
    <iframe src="http://b.test.com/b.html" frameborder="0" ></iframe>
<script>
   $('.main input').addEventListener('input', function(){
               console.log(this.value);
               window.frames[0].postMessage(this.value,'*');
         })
 window.addEventListener('message',function(e) {
          $('.main input').value = e.data
                   console.log(e.data);
   });
   function $(id){
    return document.querySelector(id);
  }
</script>

http://a.test.com/a.html通過postMessage()方法向跨域的iframe頁面http://b.test.com/b.html傳遞消息,b.html監(jiān)聽window的message事件就可以

<input id="input" type="text" placeholder="http://b.test.com/b.html">
<script>
$('#input').addEventListener('input', function(){
    window.parent.postMessage(this.value, '*');
})
window.addEventListener('message',function(e) {
        $('#input').value = e.data
    console.log(e.data);
});
function $(id){
    return document.querySelector(id);
}   
</script>

JSONP 的原理是什么

JSONP不是最新的數(shù)據(jù)格式,是json跨域獲取的解決方案决采,通過jsonp獲取的數(shù)據(jù)作為js的參數(shù)運行。瀏覽器有同源策略树瞭,會把跨域請求都禁止了晒喷,但是html的<script>標(biāo)簽,不受同源策略的影響衣盾,可以從其他源獲取數(shù)據(jù)爷抓,所以我們可以通過script標(biāo)簽废赞,引入其他源的數(shù)據(jù)唉地,通過js代碼進(jìn)行解析。先定義處理函數(shù)functionname极颓,然后通過添加一個<script>元素群嗤,src的地址是后端接口,在地址后加個請求參數(shù)callback=函數(shù)名骇径,這個就是處理函數(shù)的函數(shù)名破衔,向服務(wù)器請求JSON數(shù)據(jù)晰筛,服務(wù)器收到請求后拴袭,把數(shù)據(jù)放在回調(diào)函數(shù)中返回,返回的functionname(data)會放在script標(biāo)簽作為js執(zhí)行,所以會調(diào)用functionname(data),將data作為函數(shù)的參數(shù)怜瞒。

CORS是什么

CORS是跨源資源分享(Cross-Origin Resource Sharing)的縮寫盼砍。它是W3C標(biāo)準(zhǔn)浇坐,是跨源AJAX請求的根本解決方法黔宛。相比JSONP只能發(fā)GET請求臀晃,CORS允許任何類型的請求。CORS需要瀏覽器和服務(wù)器同時支持案淋,現(xiàn)代瀏覽器都支持此功能踢京,IE瀏覽器要IE10以上誉碴。CORS的整個通信過程不需要用戶參與黔帕,瀏覽器會自己完成蹈丸,CORS與AJAX的同源通信一樣逻杖,在發(fā)送AJAX請求的時候奋岁,瀏覽器會自動在頭部添加一個origin字段厦取,只要服務(wù)器允許cors的約定虾攻,就可以實現(xiàn)跨域通信更鲁。
CORS兩種請求
cors有簡單請求和非簡單請求霎箍,只要滿足
1)請求方法是HEAD/GET/POST三種方法之一;
2)HTTP的頭信息不超出一下幾種字段:Accept/Accept-Encoding/Accept-Language/Cache-Control/Connection/Cookie/Host/If-Modified-Since/Referer/User-Agent/Content-Type/Content-Language澡为。其中Content-Type僅限于三個值:application/x-www-form-urlencoded漂坏、multipart/form-data、text/pain媒至。就是簡單請求顶别,如果不滿足就是非簡單請求,
簡單請求
對于簡單請求拒啰,瀏覽器直接發(fā)cors請求驯绎,在頭部添加origin字段,origin字段用來說明本次請求來自哪個源谋旦,服務(wù)器會根據(jù)這個origin剩失,決定是否同意通信册着,如果服務(wù)器不同意,也會返回正常的http響應(yīng)绽媒,瀏覽器沒發(fā)現(xiàn)有origin這個字段,就是報錯获三,表示不能跨域通信。
** 非簡單請求**
非簡單請求是對服務(wù)器有特殊要求的請求,比如請求方法是PUT/DELETE裸弦,或者Content-Type字段的類型是application/json。
非簡單請求的CORS請求窖贤,會在正式itongxin之前豌熄,增加愛一次HTTP查詢請求粤攒,叫預(yù)檢請求(preflight)纷妆。
??瀏覽器現(xiàn)詢問服務(wù)器逊拍,當(dāng)前網(wǎng)頁所在的域名是否在服務(wù)器的許可名單中,以及可以使用哪些HTTP動詞和頭信息字段谴咸。只有得到肯定答復(fù),瀏覽器才會發(fā)出正式的XMLHttpRequest請求,否則就報錯叶洞。
除了Origin字段,預(yù)檢請求的頭信息還包括兩個特殊字段:
??(1). Access-Control-Request-Method
??該字段是必須的叶雹,用來列出瀏覽器的CORS請求會用到哪些HTTP方法,例子中是POST谦炒。
??(2). Access-Control-Request-Headers
??該字段是都好分割的字符串魂莫,指定瀏覽器CORS請求會額外發(fā)送的頭信息字段,上面的例子默認(rèn)application/json對應(yīng)的額外字段是”Content-Type”山卦。
服務(wù)器收到預(yù)檢請求后藻懒,檢查Origin酷含、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,確認(rèn)允許跨源請求弥虐,并做出回應(yīng)。
如果服務(wù)器否定了預(yù)檢請求颖对,會返回一個正常的HTTP Response,但是沒有任何CORS相關(guān)的頭信息字段。這時候瀏覽器認(rèn)為i額服務(wù)器不同意預(yù)檢請求坑鱼,因此出發(fā)一個錯誤,被XMLHttpRequest對象的onerror毀掉函數(shù)捕獲。控制臺會打印出如下報錯信息。
一旦服務(wù)器通過了預(yù)檢請求,以后每次瀏覽器正常的CORS請求就都與簡單請求一樣粥脚,包括Origin字段信息搀菩。服務(wù)器的回應(yīng)也會有Access-Control-Allow-Origin字段

根據(jù)視頻里的講解演示三種以上跨域的解決方式 州既,寫成博客

博客地址

最后一個cors的介紹參考了阮一峰老師的日志实束。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末囊榜,一起剝皮案震驚了整個濱河市尺上,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖抚岗,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件亩冬,死亡現(xiàn)場離奇詭異佳遂,居然都是意外死亡巍糯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狰晚,“玉大人换棚,你說我怎么就攤上這事你弦。” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長羹蚣。 經(jīng)常有香客問我,道長戚哎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上祖灰,老公的妹妹穿的比我還像新娘三妈。我一直安慰自己咖祭,他們只是感情好浩嫌,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布每瞒。 她就那樣靜靜地躺著埠褪,像睡著了一般苹威。 火紅的嫁衣襯著肌膚如雪调违。 梳的紋絲不亂的頭發(fā)上技肩,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音辛蚊,去河邊找鬼延柠。 笑死,一個胖子當(dāng)著我的面吹牛邑商,可吹牛的內(nèi)容都是我干的摄咆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼奠骄,長吁一口氣:“原來是場噩夢啊……” “哼豆同!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起含鳞,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤影锈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蝉绷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸭廷,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年熔吗,在試婚紗的時候發(fā)現(xiàn)自己被綠了辆床。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡桅狠,死狀恐怖讼载,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情中跌,我是刑警寧澤咨堤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站漩符,受9級特大地震影響一喘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嗜暴,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一凸克、第九天 我趴在偏房一處隱蔽的房頂上張望议蟆。 院中可真熱鬧,春花似錦萎战、人聲如沸咐容。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疟丙。三九已至,卻和暖如春鸟雏,著一層夾襖步出監(jiān)牢的瞬間享郊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工孝鹊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留炊琉,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓又活,卻偏偏與公主長得像苔咪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子柳骄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1.什么是同源策略瀏覽器出于安全方面的考慮团赏,只允許與本域下的接口交互。不同源的客戶端腳本在沒有明確授權(quán)的情況下耐薯,不...
    24_Magic閱讀 491評論 0 0
  • 1- 同源策略: 首先理解什么叫同源同源指的是協(xié)議舔清、域名、端口都必須一致曲初。只要其中一個不一致都不是同源体谒。 瀏覽器中...
    osborne閱讀 175評論 0 1
  • 1: 什么是同源策略 最初,它的含義是指臼婆,A網(wǎng)頁設(shè)置的 Cookie抒痒,B網(wǎng)頁不能打開,除非這兩個網(wǎng)頁"同源",所謂...
    好奇而已閱讀 294評論 0 0
  • 題目1: 什么是同源策略 同源策略(Same Origin Policy): 瀏覽器出于安全方面的考慮, 只允許與...
    cctosuper閱讀 229評論 0 1
  • 中老年勢力這幾年可謂異軍突出,說到中老年勢力颁独,你腦子里閃過的還只是長輩群里形形色色的早安晚安表情包跟“網(wǎng)絡(luò)一線牽彩届,...
    T立方云工作平臺閱讀 387評論 0 1