日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

javascript --- [jsonp] script标签的妙用(绕过同源限制)

發布時間:2023/12/10 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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端口類似):
const express = require('express') const path = require('path') const app = express()app.use(express.static(path.join(__dirname, 'public')))app.listen(3000, () => {console.log('http://localhost:3000') })

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)傳遞
// 將回調函數掛在到全局對象上 function jsonp(options) {var script = document.createElement('script');window.fn = options.success;script.src = options.url + '?cb=fn';document.body.appendChild(script)script.onload = function(){document.body.removeChild(script);window.fn = null;} }

以上代碼,當服務器端的返回的數據很慢時,如果連續發送多個不同的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,貼上如下代碼.
<script> jsonp({url: 'http://wis.qq.com/weather/common',data: {source: 'pc',weather_type: 'forecast_1h',province: '湖北省',city: '武漢市'},success: function(data) {if (data.status == 200 && data.message) {console.log(data);}} }) </script>
  • 打開瀏覽器,輸入localhost:3000/01.html.


    訪問成功…嘻嘻.

4. 參考

源代碼

總結

以上是生活随笔為你收集整理的javascript --- [jsonp] script标签的妙用(绕过同源限制)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。