jsonp跨域原理解析(轉)

背景:

由于瀏覽器同源策略的限制,非同源下的請求,都會產生跨域問題,jsonp即是為了解決這個問題出現(xiàn)的一種簡便解決方案。

同源策略即:同一協(xié)議,同一域名,同一端口號。當其中一個不滿足時,我們的請求即會發(fā)生跨域問題。

舉個簡單的例子:

  1. http://www.abc.com:3000https://www.abc.com:3000的請求會出現(xiàn)跨域(域名、端口相同但協(xié)議不同)
  2. http://www.abc.com:3000http://www.abc.com:3001的請求會出現(xiàn)跨域(域名、協(xié)議相同但端口不同)
  3. http://www.abc.com:3000http://www.def.com:3000的請求會出現(xiàn)跨域(域名不同)

突破同源策略限制:

現(xiàn)在知道了源策略,那我們就來看下jsonp是如何突破同源策略的限制實現(xiàn)跨域的

首先,不知道大家有沒有注意,不管是我們的script標簽的src還是img標簽的src,或者說link標簽的href他們沒有被同源策略所限制,比如我們有可能使用一個網(wǎng)絡上的圖片,就可以請求得到

<img src="https://ss3.baidu.com/9fo3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=6d0bf83bda00baa1a52c41bb7711b9b1/0b55b319ebc4b745b19f82c1c4fc1e178b8215d9.jpg">

src或href鏈接的靜態(tài)資源,本質上來說也是一個get請求,拿csdn上的靜態(tài)資源舉例:

image

可以看到,確實是個get請求無疑。同理img標簽的src和link標簽的href也會發(fā)送一個get請求去請求靜態(tài)資源。那么我們通過這點,是不是發(fā)現(xiàn)了點什么,這些標簽的src和link屬性,并沒有受同源策略的限制。說到這里jsonp的實現(xiàn)原理就浮出水面了。

jsonp就是使用同源策略這一“漏洞”,實現(xiàn)的跨域請求(這也是jsonp跨域只能用get請求的原因所在)。想象一下,既然是個get請求,那么服務端一定可以接收到,并做出反饋。ok,知道這兩點之后,我們開始具體使用jsonp進行跨域請求。

JSONP跨域實現(xiàn):

根據(jù)上邊所說的,我們要用過利用img、srcipt,link標簽的src或href屬性(到底使用那個標簽無所謂)來實現(xiàn),那么我們如何做呢,我們來看一段簡單的代碼,為了方便,我這里使用jQuery:

$('#btn').click(function(){         var frame = document.createElement('script');           frame.src = 'http://localhost:3000/article-list?name=leo&age=30&callback=func';         $('body').append(frame);        });

可以看到,讓我們點擊按鈕的時候,創(chuàng)建了一個script標簽(即會發(fā)送一個get請求到src指向的地址),src地址是"localhost:3000/article-list",這個src地址,就是我們請求的服務端接口。注意,這里我們有是那個參數(shù),name,age和callback,name和age不說了,這跟我們平時普通的get請求參數(shù)無異。主要說下callback這個參數(shù),callback參數(shù)就是核心所在。**為什么要定義callback呢?首先我們知道,這個get請求已經被發(fā)出去了,那么我們如何接口請求回來的數(shù)據(jù)呢,callback=func則可以幫我們做這件事。我們繼續(xù)看下邊的代碼 **

<button id="btn">點擊</button>  <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>  <script>    $('#btn').click(function(){           var frame = document.createElement('script');           frame.src = 'http://localhost:3000/article-list?name=leo&age=30&callback=func';         $('body').append(frame);        });             function func(res){         alert(res.message+res.name+'你已經'+res.age+'歲了');     }  </script>

這里可以看到,我們聲明了一個func函數(shù),但沒有執(zhí)行,你可以想一下,如果服務端接口到get請求,返回的是func({message:'hello'}),這樣的話在服務端不就可以把數(shù)據(jù)通過函數(shù)執(zhí)行傳參的方式實現(xiàn)數(shù)據(jù)傳遞了嗎。

服務端代碼實現(xiàn):

接下來,我們看服務端應該如何實現(xiàn):

router.get('/article-list', (req, res) => {  console.log(req.query, '123');  let data = {    message: 'success!',    name: req.query.name,    age: req.query.age  }  data = JSON.stringify(data)  res.end('func(' + data + ')');});

ok,接下來當我們點擊提交的時候,就獲取到了服務端反回的數(shù)據(jù)。如下:

image

這樣下來,就完成了實現(xiàn)jsonp的跨域。

總結:

需要注意的是,callback參數(shù)定義的方法是需要前后端定義好的,具體什么名字,商討好就可以了。其實jsonp的整個過程就類似于前端聲明好一個函數(shù),后端返回執(zhí)行函數(shù)。執(zhí)行函數(shù)參數(shù)中攜帶所需的數(shù)據(jù),整個過程實際非常簡單易懂,如有疑問大家可以在下方留言,我會及時回復。

作者:機智的趙先生
鏈接:https://me.csdn.net/badmoonc
來源:CSND
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容