JavaScript筆記之跨域

在了解跨域之前,我們先了解下什么是同源策略

1.什么是同源策略?

同源策略/SOP(Same origin policy)是一種約定憋沿,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能亚斋,如果缺少了同源策略毅待,瀏覽器很容易受到XSS檐涝、CSFR等攻擊拂到。所謂同源是指"協(xié)議+域名+端口"三者相同痪署,即便兩個(gè)不同的域名指向同一個(gè)ip地址,也非同源兄旬。

同源

不同源

需要注意的是: 對(duì)于當(dāng)前頁(yè)面來(lái)說(shuō)頁(yè)面存放的 JS 文件的域不重要,重要的是加載該 JS 頁(yè)面所在什么域

2.什么是跨域领铐?

瀏覽器從一個(gè)域名的網(wǎng)頁(yè)去請(qǐng)求另一個(gè)域名的資源時(shí)悯森,域名、端口罐孝、協(xié)議任一不同呐馆,都是跨域

3.跨域的幾種解決方式

  1. 使用JSONP方式實(shí)現(xiàn)跨域
    原理:JSONP是通過(guò)script標(biāo)簽加載數(shù)據(jù)的方式去獲取數(shù)據(jù)當(dāng)做JS代碼來(lái)執(zhí)行。具體操作方法:提前在頁(yè)面上聲明一個(gè)函數(shù)(這個(gè)函數(shù)用來(lái)處理后端返回的數(shù)據(jù))莲兢,函數(shù)名通過(guò)接口的方式傳遞給后臺(tái)汹来;后臺(tái)解析到函數(shù)名后在原始數(shù)據(jù)上[包裹]這個(gè)函數(shù)名(即相當(dāng)于將后臺(tái)返回來(lái)的數(shù)據(jù)作為函數(shù)的參數(shù),執(zhí)行該函數(shù))改艇,發(fā)送給前端收班。換句話說(shuō),JSONP 需要對(duì)應(yīng)接口的后端的配合才能實(shí)現(xiàn)谒兄。
      1. 定義數(shù)據(jù)處理函數(shù)_fun
      2. 創(chuàng)建script標(biāo)簽摔桦,src的地址執(zhí)行后端接口,最后加個(gè)參數(shù)  callback=_fun
      3. 服務(wù)端在收到請(qǐng)求后承疲,解析參數(shù)邻耕,計(jì)算返還數(shù)據(jù),輸出 fun(data) 字符串燕鸽。
      4. fun(data)會(huì)放到script標(biāo)簽做為js執(zhí)行兄世。此時(shí)會(huì)調(diào)用fun函數(shù),將data做為參數(shù)啊研。
    
  2. CORS
    CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing)御滩,是一種 ajax 跨域請(qǐng)求資源的方式,支持現(xiàn)代瀏覽器党远,IE支持10以上削解。
    實(shí)現(xiàn)方式:當(dāng)你使用 XMLHttpRequest 發(fā)送請(qǐng)求時(shí),瀏覽器發(fā)現(xiàn)該請(qǐng)求不符合同源策略沟娱,會(huì)給該請(qǐng)求加一個(gè)請(qǐng)求頭:Origin氛驮,后臺(tái)進(jìn)行一系列處理,如果確定接受請(qǐng)求則在返回結(jié)果中加入一個(gè)響應(yīng)頭:Access-Control-Allow-Origin; 瀏覽器判斷該相應(yīng)頭中是否包含 Origin 的值济似,如果有則瀏覽器會(huì)處理響應(yīng)柳爽,我們就可以拿到響應(yīng)數(shù)據(jù),如果不包含瀏覽器直接駁回碱屁,這時(shí)我們無(wú)法拿到響應(yīng)數(shù)據(jù)磷脯。所以 CORS 的表象是讓你覺(jué)得它與同源的 ajax 請(qǐng)求沒(méi)啥區(qū)別,代碼完全一樣娩脾。
  3. 降域
    此方案僅限主域相同赵誓,子域不同的跨域應(yīng)用場(chǎng)景。
    實(shí)現(xiàn)原理:兩個(gè)頁(yè)面都通過(guò)js強(qiáng)制設(shè)置document.domain為基礎(chǔ)主域柿赊,就實(shí)現(xiàn)了同域俩功。
       <script>
            document.domain = 'xxx.com'
       </script>
    
  4. postMessage
    window.postMessage() 方法可以安全地實(shí)現(xiàn)跨源通信
    從廣義上講,一個(gè)窗口可以獲得對(duì)另一個(gè)窗口的引用(比如 targetWindow = window.opener)碰声,然后在窗口上調(diào)用 targetWindow.postMessage() 方法分發(fā)一個(gè) MessageEvent, MessageEvent 是接口代表一段被目標(biāo)對(duì)象接收的消息诡蜓。")消息。接收消息的窗口可以根據(jù)需要自由處理此事件胰挑。傳遞給 window.postMessage() 的參數(shù)(比如 message )將通過(guò)消息事件對(duì)象暴露給接收消息的窗口
  • 用法:postMessage(data,origin,[transfer])方法接受兩個(gè)參數(shù)蔓罚,第三個(gè)參數(shù)可選椿肩。
  • data: html5規(guī)范支持任意基本類型或可復(fù)制的對(duì)象
  • origin: 協(xié)議+主機(jī)+端口號(hào),也可以設(shè)置為*豺谈,表示可以傳遞給任意窗口郑象,如果要指定和當(dāng)前窗口同源的話設(shè)置為/
    <div class="ct">
    <h1>使用postMessage實(shí)現(xiàn)跨域</h1>
    <div class="main">
        <input type="text" placeholder="http://a.jrg.com:8080/a.html">
    </div>
    <iframe src="http://localhost:8080/b.html" frameborder="0" ></iframe>
    </div>
     //a.html里的js代碼
    <script>
      $('.main input').addEventListener('input', function(){
            console.log(this.value);
            window.frames[0].postMessage(this.value,'*');//向b.html傳送跨域數(shù)據(jù)
    
        })
      // 接收b.html返回回來(lái)的數(shù)據(jù)
      window.addEventListener('message',function(e) {
              $('.main input').value = e.data  
                console.log(e.data);
      });
    </script>
    //b.html里的js代碼
    <script>
    //接收a.html的數(shù)據(jù)
    window.addEventListener('message',function(e) {
        $('#input').value = e.data
            console.log(e.data);
    });   
    //返回?cái)?shù)據(jù)給a.html
     $('#input').addEventListener('input', function(){
      window.parent.postMessage(this.value, '*');
    })
    </script>
    

4. CORS具體的實(shí)現(xiàn)代碼

  • 使用XMLHttpRequest發(fā)送請(qǐng)求,瀏覽器發(fā)現(xiàn)該請(qǐng)求不符合同源策略茬末,會(huì)給該請(qǐng)求加一個(gè)請(qǐng)求頭:Origin厂榛;后臺(tái)進(jìn)行處理,在返回結(jié)果中加入一個(gè)響應(yīng)頭:Access-Control-Allow-Origin丽惭;瀏覽器判斷該相應(yīng)頭中是否包含 Origin的值击奶,有則處理響應(yīng),無(wú)則直接駁回
  • res.setHeader('Access-Control-Allow-Origin','127.0.0.1:8080')
  • res.setHeader('Access-Control-Allow-Origin','*')
  • index.html頁(yè)面
      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
      </head>
      <body>
        <div class="container">
          <ul class="news"></ul>
          <button class="show">show news</button>
        </div>
    
        <script>
          function $(selector){
            return document.querySelector(selector)
          }
          function appendHtml(news){
            var html = ''
            for (var i=0; i<news.length; i++){
              html += '<li>'+ news[i] + '</li>'
            }
            $('.news').innerHTML = html
          }
          $('.show').addEventListener('click', function(){
            var xhr = new XMLHttpRequest()
            xhr.open('GET', 'http://127.0.0.1:8080/getNews', true)
            
            xhr.onload = function(){
              appendHtml(JSON.parse(xhr.responseText))
            }
            xhr.send()
          })
        </script>
      </body>
      </html>
    
  • server.js
    var http = require('http')
    var fs = require('fs')
    var path = require('path')
    var url = require('url')
    
    http.createServer(function(req,res){
      var pathObj = url.parse(req.url,true)
      switch (pathObj.pathname){
        case '/getNews':
          var news = [
            "這是第一條消息责掏,獲取了消息一",
            "這是第二條消息柜砾,獲取了消息二",
            "這是第三條消息,獲取了消息三"
          ]
          res.setHeader('Access-Control-Allow-Origin','127.0.0.1:8080')
          res.end(JSON.stringify(news))
          break;
        
          default:
            fs.readFile(path.join(__dirname,pathObj.pathname),function(e,data){
              if(e){
                res.writeHead(404,'not found')
                res.end('<h1>404 Not Found</h1>')
              } else {
                res.end(data)
              }
            })
          } 
      }).listen(8080)
    
  • 啟動(dòng)終端拷橘,執(zhí)行 node server.js
    啟動(dòng)服務(wù)器.PNG
  • 瀏覽器打開(kāi)http://localhost:8080/index.html ,查看效果和網(wǎng)絡(luò)請(qǐng)求
    localhost.PNG
  • 點(diǎn)擊[show news]按鈕 局义,會(huì)出現(xiàn)下圖報(bào)錯(cuò),因?yàn)楹蠖嗽O(shè)置的Access-Control-Allow-Origin127.0.0.1:8080
    wrong1.PNG
  • 瀏覽器打開(kāi)http://127.0.0.1:8080/index.html ,點(diǎn)擊[show news]按鈕 冗疮,此時(shí)網(wǎng)頁(yè)能正常響應(yīng)
    ok1.PNG
  • 若將 res.setHeader('Access-Control-Allow-Origin','127.0.0.1:8080')
    改成 res.setHeader('Access-Control-Allow-Origin','*')萄唇,打開(kāi)服務(wù)器,瀏覽器打開(kāi)http://localhost:8080/index.html,瀏覽器頁(yè)能正常響應(yīng)术幔。*表示匹配所有的窗口
    ok2.PNG

以上為簡(jiǎn)單為跨域簡(jiǎn)單總結(jié)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末另萤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子诅挑,更是在濱河造成了極大的恐慌四敞,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拔妥,死亡現(xiàn)場(chǎng)離奇詭異忿危,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)没龙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門铺厨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人硬纤,你說(shuō)我怎么就攤上這事解滓。” “怎么了筝家?”我有些...
    開(kāi)封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵洼裤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我溪王,道長(zhǎng)腮鞍,這世上最難降的妖魔是什么值骇? 我笑而不...
    開(kāi)封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮缕减,結(jié)果婚禮上雷客,老公的妹妹穿的比我還像新娘芒珠。我一直安慰自己桥狡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布皱卓。 她就那樣靜靜地躺著裹芝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪娜汁。 梳的紋絲不亂的頭發(fā)上嫂易,一...
    開(kāi)封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音掐禁,去河邊找鬼怜械。 笑死,一個(gè)胖子當(dāng)著我的面吹牛傅事,可吹牛的內(nèi)容都是我干的缕允。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蹭越,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼障本!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起响鹃,我...
    開(kāi)封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驾霜,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后买置,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體粪糙,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年忿项,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蓉冈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倦卖,死狀恐怖洒擦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情怕膛,我是刑警寧澤熟嫩,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站褐捻,受9級(jí)特大地震影響掸茅,放射性物質(zhì)發(fā)生泄漏椅邓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一昧狮、第九天 我趴在偏房一處隱蔽的房頂上張望景馁。 院中可真熱鬧,春花似錦逗鸣、人聲如沸合住。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)透葛。三九已至,卻和暖如春卿樱,著一層夾襖步出監(jiān)牢的瞬間僚害,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工繁调, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萨蚕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓蹄胰,卻偏偏與公主長(zhǎng)得像岳遥,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子烤送,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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

  • 什么是跨域 跨域寒随,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的帮坚,是瀏覽器對(duì)JavaScript實(shí)...
    Yaoxue9閱讀 1,286評(píng)論 0 6
  • 什么是跨域 跨域妻往,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的试和,是瀏覽器對(duì)JavaScript實(shí)...
    他方l閱讀 1,059評(píng)論 0 2
  • 什么是跨域 跨域讯泣,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的阅悍,是瀏覽器對(duì)JavaScript實(shí)...
    HeroXin閱讀 831評(píng)論 0 4
  • 題目1: 什么是同源策略 瀏覽器出于安全考慮好渠,只允許與本域下的接口交互。不同源的客戶端腳本在沒(méi)有明確授權(quán)的情況下节视,...
    saintkl閱讀 234評(píng)論 0 0
  • Source調(diào)試JS代碼 理解單步調(diào)試拳锚,單步進(jìn)入塊,單步退出塊的區(qū)別 單步調(diào)試F10 跳過(guò)當(dāng)前函數(shù)調(diào)用 單步進(jìn)入塊...
    pepsi1000閱讀 660評(píng)論 0 0