當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
javascript --- [jsonp] script标签的妙用(绕过同源限制)
生活随笔
收集整理的這篇文章主要介紹了
javascript --- [jsonp] script标签的妙用(绕过同源限制)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 同源
1.1 什么是同源
協議、域名、端口號相同
1.2 為什么有同源政策
同源政策是為了保護用戶信息的安全,放置惡意的網站竊取數據。最初的同源政策是指A網站再客戶端設置的Cookie,B網站是不能訪問的.
隨著互聯網的發展,同源政策也越來越嚴格,在不同源的情況下,其中有一項規定就是無法向非同源地址發送Ajax請求,如果請求,瀏覽器就會報錯
2. jsonp
- jsonp是json with padding(將JSON數據作為填充內容)的縮寫,它不屬于Ajax請求,但它可以模擬Ajax請求。
- 核心:利用了script標簽可以向非同源端的服務器發送請求的特性,加載完畢后,相當于把服務器返回的內容當作JavaScript代碼執行
2.1 準備工作
- 準備2個服務器,一個監聽3000端口(作為客戶端),一個監聽3001端口(作為服務端)
- 兩個服務器都暴露靜態資源,3000端口服務器代碼如下(3001端口類似):
2.2 JSONP的實現
1.在3001端口服務器中添加如下代碼:
app.get('/jsonp',(req,res)=>{const data = `fn({name:'Marron', age:18, remarks:'JSONP測試'})`;res.send(data) })2.先定義一個全局函數,在使用script標簽加載S2服務器的資源
<script>// 假設服務器返回的數據存儲在data中function fn(data) {console.log(data);} </script> <!-- 使用jsonp加載資源 --> <script src="http://localhost:3001/jsonp"></script>2.3 JSONP代碼優化
2.3.1 動態創建script標簽發送jsonp請求
- 實際項目中,不可能將script標簽靜態的寫死…因此需要動態的創建script標簽,用script標簽的src的跨瀏覽器性,來發送請求.
1.客戶端將函數名稱傳遞到服務器端
<script src="http://localhost:3001/jsonp?cb=fn"></script>2.將script請求的發送變成動態請求
<script>var srcipt = document.creatElement('script');script.src="http://localhost:3001/jsonp?cb=fn"document.body.appendChild(script); </script>3.發送請求后,刪除掉script標簽
<script>var srcript = document.createElement('script');script.src="http://localhost:3001/jsonp?cb=fn";document.body.appendChild(script);script.onload = function (){document.body.removeChild(script)} </script>4.封裝jsonp
function jsonp(url) {var script = document.createElement('script')script.src = urldocument.body.appendChild(script)script.onload = function() {document.body.removeChild(script)} }2.3.2 將回調函數封裝進的JSONP
由于上面封裝的JSONP它調用的函數和JSONP函數是分離的,破壞了JSONP的封裝性,下面嘗試將JSONP的回調函數封裝如JSONP中,請求參數如下:
jsonp({url: 'http://localhost:3001/better?cb=fn',success: function(){} })產生了如下2個問題:
- 回調函數不再是一個全局變量,即當使用script標簽加載完畢只會,找不到回調函數
- success是一個匿名函數,傳遞到后端是沒有名稱(如 fn)傳遞
以上代碼,當服務器端的返回的數據很慢時,如果連續發送多個不同的JSONP請求時,會導致多個請求的回調函數是同一個.
解決辦法是,每次調用回調函數時,名字不能相同(即隨機產生一個名字)
// 每次隨機產生一個名字 function jsonp(options) {var script = document.createElement('script')var fn = 'fn'+ Math.random().toString().replace('.','')window[fn] = options.successscript.src = options.url + '?cb=' + fndocument.body.appendChild(script)script.onload = function() {document.body.removeChild(script)// 用完后釋放內存delete window[fn]} }2.3.3 將get請求參數封裝進jsonp
function jsonp(options) {var script = document.createElement('script')var fn ='fn' +Math.random().toString().replace('.', '')window[fn] = options.successvar params = []params.push('callback=' + fn)for (let attr in options.data) {params.push(attr + '=' + options.data[attr])}params = params.join('&')script.src = options.url + '?' + paramsdocument.body.appendChild(script)script.onload = function() {document.body.removeChild(script)delete window[fn]} }3. json實戰
- 使用上面封裝好的jsonp去獲取騰訊天氣的代碼
3.1 尋找api
- 瀏覽器打開騰訊天氣
- 按F12打開調試工具,選擇NetWork -> JS
- 可以看到此處域名(tianqi.qq.com)使用到了域名(wis.qq.com)的數據,產生了跨域,并且它傳過去的參數含有callback字段.可以假設使用了JSONP技術進行跨域獲取數據
3.2 使用封裝的JSONP函數獲取數據.
- 在3000端口的public目錄下新建01.html,貼上如下代碼.
- 打開瀏覽器,輸入localhost:3000/01.html.
訪問成功…嘻嘻.
4. 參考
源代碼
總結
以上是生活随笔為你收集整理的javascript --- [jsonp] script标签的妙用(绕过同源限制)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html绘制波形图,JS实现波形图
- 下一篇: javascript --- 瀑布流的