JavaScript通過JSONP實(shí)現(xiàn)跨域數(shù)據(jù)請求技術(shù)
當(dāng)談到 JSONP,就像是在談?wù)撃阍谝粓雠蓪ι险J(rèn)識的新朋友一樣,讓我們從頭開始介紹。
什么是 JSONP
JSONP,全稱 “JSON with Padding”,譯為“帶回調(diào)的 JSON”,是一種利用 <script> 標(biāo)簽進(jìn)行跨域數(shù)據(jù)請求的技術(shù)。它允許你在網(wǎng)頁中請求來自其他域的數(shù)據(jù),而無需擔(dān)心瀏覽器的同源策略(Same-Origin Policy)帶來的限制。
JSONP 不是一門編程語言,也不是什么特別的技術(shù),它更像一個(gè)漏洞,程序員可以利用這個(gè)漏洞,實(shí)現(xiàn)跨域(可以簡單理解為跨域名)傳輸數(shù)據(jù)。
JSONP 是 JSON 的一種使用模式,通過 JSONP 可以繞過瀏覽器的同源策略,進(jìn)行跨域請求。
在進(jìn)行 Ajax 請求時(shí),由于同源策略的影響,不能進(jìn)行跨域請求,而 <script> 標(biāo)簽的 src 屬性卻可以加載跨域的 JavaScript 腳本,JSONP 就是利用這一特性實(shí)現(xiàn)的。與普通的 Ajax 請求不同,在使用 JSONP 進(jìn)行跨域請求時(shí),服務(wù)器不再返回 JSON 格式的數(shù)據(jù),而是返回一段調(diào)用某個(gè)函數(shù)的 JavaScript 代碼,在 src 屬性中調(diào)用,來實(shí)現(xiàn)跨域。
JSONP 的優(yōu)點(diǎn)是兼容性好,在一些老舊的瀏覽器種也可以運(yùn)行,但它的缺點(diǎn)也非常明顯,那就是只能進(jìn)行 GET 請求。
以一個(gè)簡單的比喻來說,就像你在一家餐館點(diǎn)菜一樣。你可以在自己家里使用電話點(diǎn)餐,然后等著外賣送達(dá),而不需要親自去餐館。JSONP允許你在當(dāng)前頁面中加載其他網(wǎng)站的數(shù)據(jù),就像是通過電話點(diǎn)餐一樣輕松。
同源策略是由 Netscape(網(wǎng)景) 提出的一個(gè)著名的安全策略,現(xiàn)在所有支持 JavaScript 的瀏覽器都會使用這個(gè)策略。
所謂同源是指域名、協(xié)議、端口都相同。以 http://www.xxxxx.com:80/ 為例,http:// 為協(xié)議,域名是 www.xxxxx.com,端口是80(提示:80 為默認(rèn)端口,可以省略,若為其它端口則必須顯示定義)。
為了安全,瀏覽器不允許進(jìn)行跨域請求。當(dāng)我們通過 Ajax 在網(wǎng)頁和服務(wù)器之間發(fā)送或接收數(shù)據(jù)時(shí),需要保證網(wǎng)頁與所請求的地址是同源的,否則無法請求成功。同源策略可以防止 JavaScript 腳本從您的網(wǎng)站中讀取數(shù)據(jù),并將數(shù)據(jù)發(fā)送到其它的網(wǎng)站。如果沒有同源策略,很有可能會有惡意的程序泄露您網(wǎng)站中的內(nèi)容。
雖然同源策略在一定程度上提高了網(wǎng)站的安全,但也會給程序員帶來一些麻煩,例如在訪問一些開發(fā)接口時(shí),由于同源策略的存在,會調(diào)用失敗。要解決這種問題就需要用到跨域,跨域的方法有許多種,其中最經(jīng)典的就是 JSONP。
JSONP 的歷史背景
JSONP的歷史可以追溯到當(dāng)時(shí)的 Web 1.0 時(shí)代,這時(shí)候互聯(lián)網(wǎng)還沒有那么復(fù)雜??缬蛘埱蟛⒉皇且粋€(gè)大問題,因?yàn)榫W(wǎng)頁之間的交互性相對較少。但隨著 Web 2.0 的興起,網(wǎng)頁變得更加交互和動態(tài),跨域請求的需求也隨之增加。
當(dāng)時(shí),JSONP就像是一位突然出現(xiàn)的超級英雄,解決了跨域請求的難題。它簡單、有效,并且可以在各種瀏覽器上運(yùn)行,這使得它迅速成為了 Web 開發(fā)人員的首選。
JSONP 的優(yōu)點(diǎn)和局限性
JSONP的優(yōu)點(diǎn)就像是一把多功能的瑞士軍刀,幫助你輕松應(yīng)對各種場景:
簡單易用: JSONP的原理簡單明了,幾行代碼就可以實(shí)現(xiàn)跨域請求。
兼容性好: JSONP在各種瀏覽器上都能良好運(yùn)行,無需擔(dān)心兼容性問題。
適用性廣: JSONP不僅可以用于數(shù)據(jù)請求,還可以用于跨域數(shù)據(jù)分析和可視化等各種場景。
然而,就像是每個(gè)超級英雄都有自己的弱點(diǎn)一樣,JSONP也有一些局限性:
僅支持 GET 請求: JSONP只能通過 <script> 標(biāo)簽發(fā)起 GET 請求,無法發(fā)送其他類型的請求,如 POST 請求。
安全性問題: JSONP存在安全隱患,因?yàn)樗峭ㄟ^動態(tài)插入 <script> 標(biāo)簽來加載數(shù)據(jù)的,可能被惡意利用來執(zhí)行跨站腳本攻擊(XSS)。
盡管有這些局限性,但在許多場景下,JSONP仍然是一個(gè)非常有用且方便的解決方案。
JSONP 的工作原理
讓我們用一個(gè)生動的比喻來解釋JSONP的工作原理,就像是在派對上傳遞紙條一樣。
假設(shè)你在派對上認(rèn)識了一個(gè)新朋友,但是你們無法直接交談,因?yàn)槟銈儽桓糸_了。你想要向他詢問一些問題,但是你只能通過傳遞紙條來進(jìn)行溝通。這就是JSONP的基本思想。
在Web開發(fā)中,當(dāng)你需要從一個(gè)網(wǎng)站獲取數(shù)據(jù),但是由于瀏覽器的同源策略(Same-Origin Policy)限制,你無法直接進(jìn)行跨域請求。JSONP的解決方案是利用 <script> 標(biāo)簽來加載遠(yuǎn)程數(shù)據(jù),繞過了同源策略的限制,實(shí)現(xiàn)了跨域數(shù)據(jù)請求。
就像是你通過傳遞紙條來與派對上的朋友交流一樣,JSONP通過動態(tài)創(chuàng)建 <script> 標(biāo)簽,加載包含數(shù)據(jù)的遠(yuǎn)程腳本,然后利用回調(diào)函數(shù)將數(shù)據(jù)傳遞給你的網(wǎng)頁,實(shí)現(xiàn)了跨域數(shù)據(jù)的獲取。
JSONP 的實(shí)現(xiàn)步驟
讓我們用一個(gè)有趣的比喻來解釋JSONP的實(shí)現(xiàn)步驟,就像是在操縱一臺神奇的魔法機(jī)器一樣。
客戶端實(shí)現(xiàn) callback 函數(shù)
創(chuàng)建回調(diào)函數(shù)
首先,你需要準(zhǔn)備好一個(gè)魔法咒語,也就是你的回調(diào)函數(shù)。這個(gè)回調(diào)函數(shù)就像是一段魔法代碼,會在你請求數(shù)據(jù)時(shí)被觸發(fā),并且接收到你想要的數(shù)據(jù)。
就像是在準(zhǔn)備施展一場魔法一樣,你需要先在網(wǎng)頁的某個(gè)地方創(chuàng)建一個(gè)函數(shù),比如叫做 handleData。這個(gè)函數(shù)會接收一個(gè)參數(shù),用來接收服務(wù)器返回的數(shù)據(jù)。當(dāng)數(shù)據(jù)到達(dá)時(shí),這個(gè)函數(shù)就會被調(diào)用,就像是你在念咒語一樣。
function handleData(data) {
// 在這里處理接收到的數(shù)據(jù)
console.log(data);
}動態(tài)插入<script>標(biāo)簽
接下來,你需要操縱魔法機(jī)器,讓它幫你完成跨域數(shù)據(jù)請求的任務(wù)。你會用到的工具就是 <script> 標(biāo)簽,這個(gè)標(biāo)簽有著神奇的能力,可以加載其他域名下的腳本。
就像是在操作一臺魔法機(jī)器一樣,你需要創(chuàng)建一個(gè) <script> 標(biāo)簽,并將遠(yuǎn)程數(shù)據(jù)的URL作為它的src屬性值。這樣,瀏覽器就會開始下載并執(zhí)行這個(gè)URL指定的腳本文件。
var oscript = document.createElement('script');
oscript.src = 'http://example.com/aaa?callback=handleData';
document.body.appendChild(oscript);在這段代碼中,我們創(chuàng)建了一個(gè) <script> 標(biāo)簽,并設(shè)置了它的src屬性為遠(yuǎn)程數(shù)據(jù)的URL,同時(shí)通過 callback=handleData 的參數(shù)告訴服務(wù)器,當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí),請調(diào)用我們之前準(zhǔn)備好的魔法咒語 handleData。
請求數(shù)據(jù)
最后,當(dāng)魔法機(jī)器收到你的指令時(shí),它會開始運(yùn)轉(zhuǎn),發(fā)送請求并等待服務(wù)器的響應(yīng)。服務(wù)器收到請求后,會將數(shù)據(jù)包裝在之前指定的回調(diào)函數(shù)中,并返回給你的網(wǎng)頁。
就像是在等待魔法機(jī)器完成任務(wù)一樣,你只需要耐心等待,當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí),你的魔法咒語 handleData 就會被觸發(fā),接收到你想要的數(shù)據(jù)。
function handleData(data) {
console.log('收到數(shù)據(jù):', data);
}當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí),你會看到控制臺輸出了你想要的數(shù)據(jù),就像是魔法成功施展一樣。這就是JSONP的實(shí)現(xiàn)步驟,通過動態(tài)插入 <script> 標(biāo)簽,利用回調(diào)函數(shù)實(shí)現(xiàn)了跨域數(shù)據(jù)的請求和獲取。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- jsonp接口調(diào)用 -->
<script>
var oscript = document.createElement("script")
oscript.src = "http://localhost:3000/api/aaa?callback=handleData"
document.body.appendChild(oscript)
function handleData(obj) {
console.log(obj);
}
</script>
</body>
</html>服務(wù)端 JSONP 格式數(shù)據(jù)
var http = require("http")
var url = require("url")
http.createServer((req, res) => {
var urlobj = url.parse(req.url, true)
console.log(urlobj.query.callback);
switch (urlobj.pathname) {
case "/api/aaa":
res.end(`${urlobj.query.callback} (${JSON.stringify({
name: '張三',
age: 21
})})`)
break;
default:
res.end("404")
}
}).listen(3000, () => {
console.log("start");
})JSONP 總結(jié)
通過 jsonp,我們可以避開瀏覽器的同源策略,從而進(jìn)行跨域請求。jsonp 是利用 HTML 標(biāo)簽的 src 屬性引用資源不受同源策影響的特性來實(shí)現(xiàn)的,實(shí)現(xiàn)步驟如下:
① 通過動態(tài)創(chuàng)建 script 標(biāo)簽,其 scr 指向非同源的 url,并傳遞一個(gè) callback 參數(shù)給服務(wù)端;
② 服務(wù)器返回一個(gè)以 callback 參數(shù)作為函數(shù)名的函數(shù)的調(diào)用和一系列參數(shù);
③ 頁面接收到響應(yīng)后執(zhí)行回調(diào)并對數(shù)據(jù)進(jìn)行處理。
注意:服務(wù)器返回的內(nèi)容,必須是一段可執(zhí)行的 JavaScript 代碼,不能是其它內(nèi)容。
JSONP 的安全性問題
讓我們以一個(gè)有趣的比喻來解釋JSONP的安全性問題,就像是在保護(hù)自己的城堡免受惡意入侵一樣。
JSONP 存在的安全隱患
想象一下,你的城堡是你的網(wǎng)站,而城墻是瀏覽器的同源策略,它保護(hù)著你的城堡不受外界的侵?jǐn)_。但是有一天,一群壞人試圖利用城堡內(nèi)的一個(gè)小門(JSONP)來進(jìn)行入侵。
JSONP存在的安全隱患就像是城堡中的小門一樣,它可以繞過瀏覽器的同源策略,允許從其他域名獲取數(shù)據(jù)。但是如果沒有妥善地保護(hù)這個(gè)小門,惡意攻擊者可能會利用它來進(jìn)行跨站腳本攻擊(XSS)或者盜取用戶的信息。
當(dāng)你使用JSONP來加載遠(yuǎn)程腳本時(shí),你其實(shí)是在邀請外界的數(shù)據(jù)進(jìn)入你的網(wǎng)站,就像是開了城門一樣。如果你不小心,可能會讓不懷好意的數(shù)據(jù)進(jìn)入你的網(wǎng)站,造成安全風(fēng)險(xiǎn)。
如何保護(hù) JSONP 請求的安全性
為了保護(hù)你的城堡免受惡意入侵,你需要采取一些安全措施來保護(hù)JSONP請求的安全性。
首先,你可以在使用JSONP時(shí)謹(jǐn)慎選擇可信任的數(shù)據(jù)源,就像是在選擇你的盟友一樣。確保你從可信任的服務(wù)器獲取數(shù)據(jù),避免從不信任的源加載腳本。
其次,你可以對從JSONP獲取的數(shù)據(jù)進(jìn)行嚴(yán)格的驗(yàn)證和過濾,就像是檢查城堡門口的行人一樣。確保你接收到的數(shù)據(jù)是你期望的格式和內(nèi)容,避免惡意數(shù)據(jù)的注入和執(zhí)行。
最后,你可以考慮使用其他安全性更好的替代方案,比如CORS(跨域資源共享)或者代理服務(wù)器,來替代JSONP。這些方案雖然可能更復(fù)雜一些,但是可以提供更高級的安全保護(hù),避免了JSONP存在的一些安全隱患。
通過這些安全措施,你就可以有效地保護(hù)JSONP請求的安全性,確保你的網(wǎng)站免受惡意攻擊的威脅。
JSONP 的應(yīng)用場景
讓我們以一個(gè)有趣的比喻來解釋JSONP的應(yīng)用場景,就像是在一場冒險(xiǎn)中利用神奇道具一樣。
跨域數(shù)據(jù)獲取
假設(shè)你是一位勇敢的探險(xiǎn)家,正在探索未知的領(lǐng)域。你需要從其他地方獲取數(shù)據(jù)來了解這個(gè)世界的各種信息,但是你發(fā)現(xiàn)有些數(shù)據(jù)被限制在其他領(lǐng)域中,無法直接獲取。
這時(shí),JSONP就像是一把神奇的鑰匙,可以打開這些數(shù)據(jù)的大門,讓你輕松獲取到需要的信息。你只需要通過JSONP發(fā)起跨域請求,就能夠從其他領(lǐng)域獲取到數(shù)據(jù),而不受瀏覽器的同源策略限制。
與第三方 API 的集成
繼續(xù)你的冒險(xiǎn)之旅,你發(fā)現(xiàn)了一些強(qiáng)大的魔法道具,但是它們都受到了強(qiáng)大魔法的保護(hù),無法直接使用。幸運(yùn)的是,有些魔法道具的制造商提供了API接口,可以通過JSONP來訪問。
這時(shí),JSONP就像是一個(gè)能夠與不同魔法道具對話的翻譯官,幫助你與第三方API進(jìn)行交流。你可以通過JSONP向API發(fā)送請求,獲取到你需要的魔法道具,然后在你的冒險(xiǎn)中加以利用。
跨域數(shù)據(jù)分析與可視化
你的冒險(xiǎn)之旅取得了巨大的進(jìn)展,你已經(jīng)收集到了大量的數(shù)據(jù),但是這些數(shù)據(jù)分散在不同的領(lǐng)域,你需要將它們集中起來進(jìn)行分析和可視化。
JSONP就像是一位數(shù)據(jù)搜集者,幫助你將分散在各個(gè)領(lǐng)域的數(shù)據(jù)整合起來。你可以通過JSONP向不同的領(lǐng)域發(fā)送請求,獲取到需要的數(shù)據(jù),然后通過分析和可視化工具對數(shù)據(jù)進(jìn)行處理和展示。
JSONP 與現(xiàn)代技術(shù)的關(guān)系
讓我們以一個(gè)生動的比喻來解釋JSONP與現(xiàn)代技術(shù)的關(guān)系,就像是在比較老牌武林高手與新生代新秀一樣。
JSONP 與 CORS 的比較
想象一下,JSONP就像是一位古老的武林高手,他擁有獨(dú)特的功夫,可以輕松應(yīng)對各種挑戰(zhàn)。而CORS則是一位新生代的武林新秀,他學(xué)習(xí)了現(xiàn)代武術(shù),技藝高超,但還需要時(shí)間來證明自己。
JSONP的優(yōu)勢在于其簡單易用,適用于各種場景。它就像是一把多功能的瑞士軍刀,可以應(yīng)對各種跨域請求的需求。但是JSONP只能發(fā)送GET請求,存在一些安全性問題,因此在某些情況下可能不夠安全。
而CORS則是一種更為現(xiàn)代化的跨域解決方案,它通過在服務(wù)器端設(shè)置HTTP頭部來實(shí)現(xiàn)跨域資源共享。CORS支持各種類型的HTTP請求,并且更為安全可靠。但是CORS需要服務(wù)器的支持,并且在一些老舊的瀏覽器上可能存在兼容性問題。
因此,在現(xiàn)代Web開發(fā)中,JSONP和CORS往往會根據(jù)具體的需求和場景進(jìn)行選擇。對于簡單的跨域請求,JSONP可能更加適用;而對于復(fù)雜的跨域請求,CORS可能更為合適。
JSONP 在現(xiàn)代 Web 開發(fā)中的地位
盡管CORS等新技術(shù)逐漸嶄露頭角,但JSONP在現(xiàn)代Web開發(fā)中仍然占據(jù)著重要地位。它的簡單易用和兼容性好,使得它在某些場景下仍然是首選的跨域解決方案。
特別是在與第三方API集成、數(shù)據(jù)分析與可視化等場景下,JSONP仍然是一種非常有效的解決方案。它可以幫助開發(fā)者輕松地從其他域獲取數(shù)據(jù),并且可以與各種前端框架和工具無縫集成,為Web開發(fā)帶來了便利。
雖然JSONP可能不再是唯一的跨域解決方案,但它仍然是Web開發(fā)人員工具箱中的一把利器,為跨域請求提供了簡單而有效的解決方案。
總結(jié)
總的來說,JSONP作為一種跨域數(shù)據(jù)請求的解決方案,在現(xiàn)代Web開發(fā)中仍然具有重要的地位。通過動態(tài)插入 <script> 標(biāo)簽并利用回調(diào)函數(shù),JSONP可以輕松地實(shí)現(xiàn)跨域數(shù)據(jù)獲取,克服了瀏覽器的同源策略帶來的限制。它簡單易用、兼容性好,適用于各種場景,如與第三方API集成、跨域數(shù)據(jù)分析與可視化等。
以上就是JavaScript通過JSONP實(shí)現(xiàn)跨域數(shù)據(jù)請求技術(shù)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript JSONP跨域數(shù)據(jù)請求的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
uniapp小程序權(quán)限授權(quán)封裝代碼示例
在微信小程序中,用戶公開信息包括昵稱、頭像等,這些信息可以通過微信授權(quán)獲取,下面這篇文章主要介紹了uniapp小程序權(quán)限授權(quán)封裝的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2026-05-05
JS實(shí)現(xiàn)獲取數(shù)組中最大值或最小值功能示例
這篇文章主要介紹了JS實(shí)現(xiàn)獲取數(shù)組中最大值或最小值功能,結(jié)合實(shí)例形式總結(jié)分析了javascript獲取數(shù)組最大值與最小值的三種常見操作技巧,需要的朋友可以參考下2019-03-03
前端JS/JQ實(shí)現(xiàn)頁面滾動控制代碼示例
頁面滾動可以通過jQuery實(shí)現(xiàn)多種效果,比如自動滾動、監(jiān)聽滾動事件、根據(jù)滾動位置改變元素狀態(tài)等,這篇文章主要介紹了前端JS/JQ實(shí)現(xiàn)頁面滾動控制的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-11-11
基于JavaScript實(shí)現(xiàn)定時(shí)跳轉(zhuǎn)到指定頁面
本篇文章給大家介紹基于javascript實(shí)現(xiàn)定時(shí)跳轉(zhuǎn)到指定頁面的相關(guān)知識,涉及到j(luò)s跳轉(zhuǎn)到指定頁面的相關(guān)內(nèi)容,對js跳轉(zhuǎn)到指定頁面相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧2016-01-01

