淺談Ajax跨域及其JSONP簡單實現

      網友投稿 1075 2022-05-30

      淺談Ajax跨域及其JSONP簡單實現

      淺談跨域

      跨域是指跨域名的訪問,有三種情況:

      域名不同的跨域。

      域名相同、端口不同的跨域。

      二級域名不同的跨域。

      跨域問題來源于JavaScript的"同源策略",即只有?協議+主機名+端口號 (如存在)相同,則允許相互訪問。也就是說JavaScript只能訪問和操作自己域下的資源,不能訪問和操作其他域下的資源。跨域問題是針對JS和AJAX的,html本身沒有跨域問題。

      例如下面網站:

      http://www.abc.com/a/b 調用 http://www.abc.com/d/c(非跨域)

      http://www.abc.com/a/b 調用 http://www.def.com/a/b (跨域:域名不一致)

      http://www.abc.com:8080/a/b 調用 http://www.abc.com:8081/d/c (跨域:端口不一致)

      http://www.abc.com/a/b 調用 https://www.abc.com/d/c (跨域:協議不同)

      值得一提的是:localhost和127.0.0.1雖然都指向本機,但也屬于跨域。

      同源策略

      同源策略指的是:協議+域名+端口三者皆相同,可以視為在同一個域,否則為不同域。同源策略限制了從同一個源加載的文檔或腳本如何與來自另一個源的資源進行交互。

      作用是一個用于隔離潛在惡意文件的重要安全機制。

      所限制的跨域交互包括:

      Cookie、LocalStorage、IndexdDB 等存儲內容;

      DOM 節點;

      Ajax 請求。

      跨域的常見解決方法

      jsonp:只支持 GET,不支持 POST 請求,不安全 XSS

      cors:需要后臺配合進行相關的設置

      postMessage:配合使用 iframe,需要兼容 IE6、7、8、9

      document.domain:僅限于同一域名下的子域

      websocket:需要后臺配合修改協議,不兼容,需要使用 socket.io

      proxy:使用代理去避開跨域請求,需要修改 nginx、apache 等的配置(常規解決方案)

      Ajax 其實就是向服務器發送一個 GET 或 POST 請求,然后取得服務器響應結果,返回客戶端。Ajax 跨域請求,在服務器端不會有任何問題,只是服務端響應數據返回給瀏覽器的時候,瀏覽器根據響應頭的Access-Control-Allow-Origin字段的值來判斷是否有權限獲取數據。

      因此,服務端如果沒有設置跨域字段設置,跨域是沒有權限訪問,數據被瀏覽器給攔截了。

      所以ajax本身是不可以跨域的,通過產生一個script標簽來實現跨域。因為script標簽的src屬性是沒有跨域的限制的。

      其實設置了dataType: 'jsonp'后,$.ajax方法就和ajax XmlHttpRequest沒什么關系了,取而代之的則是JSONP協議。JSONP是一個非官方的協議,它允許在服務器端集成Script tags返回至客戶端,通過javascript callback的形式實現跨域訪問。

      通俗點來說,JSONP(JSON with Padding(填充))是 JSON 的一種“使用模式”,本質不是 Ajax 請求,是 script 標簽請求。

      舉個栗子

      這里我們使用JSONP 實現一下:

      class Jsonp { constructor(req) { this.url = req.url; this.callbackName = req.callbackName; } create() { const script = document.createElement("script"); const url = `${this.url}?callback=${this.callbackName}`; script.src = url; document.getElementsByTagName("head")[0].appendChild(script); } } new Jsonp({ url: "http://127.0.0.1:8000/", callbackName: "getMsg" }).create(); function getMsg(data) { data = JSON.parse(data); console.log(`My name is ${data.name}, and ${data.age} years old.`); }

      服務端:

      const http = require("http"); const querystring = require("querystring"); const server = http.createServer((req, res) => { const url = req.url; const query = querystring.parse(url.split("?")[1]); const { callback } = query; const data = { name: "yunqinanhai", age: "18" }; res.end(`${callback}('${JSON.stringify(data)}')`); }); server.listen(8000);

      前端利用?http-server -p 8001 .,開啟一個服務,然后 Node 也開啟一個端口為 8000 的服務,運行:

      My name is yunqinanhai, and 18 years old.

      一個 JSONP 的步驟實質

      客戶端發送 script 請求,參數中帶著處理返回數據的回調函數的名字 (通常是 callback),如請求 script 的 url 是:

      http://127.0.0.1:8000/?callback=getMsg

      服務端收到請求,以回調函數名和返回數據組成立即執行函數的字符串,比如:其中 callback 的值是客戶端發來的回調函數的名字,假設回調函數的名字是 getMsg,返回腳本的內容就是:

      getMsg("{name: 'yunqinanhai', age: '18'}");

      客戶端收到 JavaScript 腳本內容后,立即執行腳本,這樣就實現了獲取跨域服務器數據的目的。

      很明顯,由于 JSONP 技術本質上利用了 script 腳本請求,所以只能實現 GET 跨域請求,這也是 JSONP 跨域的最大限制。

      由于 server 產生的響應為 json 數據的包裝(故稱之為 jsonp,即 json padding),

      形如:getMsg("{name: 'yunqinanhai', age: '18'}")

      總結

      JSONP?請求本質上是利用了 “Ajax 請求會受到同源策略限制,而 script 標簽請求不會” 這一點來繞過同源策略。

      Ajax 域名注冊服務

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:使用機器人操作系統ROS 2和仿真軟件Gazebo 9環境綜合測試教程(三)
      下一篇:Pandas中字符串處理
      相關文章
      亚洲精品人成无码中文毛片| 久久久久亚洲AV成人网| 国产亚洲视频在线观看网址| 亚洲国产中文在线视频| 久久亚洲美女精品国产精品| 亚洲成色www久久网站夜月| 亚洲色偷偷狠狠综合网| 亚洲av片一区二区三区| 国产精品亚洲а∨天堂2021| 老牛精品亚洲成av人片| 亚洲av无码专区青青草原| 精品久久久久久亚洲综合网| 亚洲日韩乱码中文字幕| 亚洲色最新高清av网站| 亚洲一卡2卡3卡4卡5卡6卡| 亚洲欧美日韩综合俺去了| 亚洲日韩av无码中文| 国产亚洲福利在线视频| 亚洲日韩久久综合中文字幕| 亚洲熟妇成人精品一区| 亚洲国产精品无码中文lv| 亚洲中文字幕久久久一区| 亚洲欧美日韩自偷自拍| 无码天堂亚洲国产AV| 亚洲精品和日本精品| 中文字幕专区在线亚洲| 亚洲精品国产精品乱码不卡√| 久久精品国产亚洲一区二区| 亚洲av无码潮喷在线观看| 久久久久久亚洲精品成人| 亚洲成在人线中文字幕| 亚洲一区二区三区深夜天堂| 亚洲综合激情五月丁香六月| 亚洲av日韩av永久在线观看| 深夜国产福利99亚洲视频| 国产精品亚洲αv天堂无码| 亚洲精品亚洲人成人网| 亚洲第一成年男人的天堂| 亚洲视频免费在线看| 2020久久精品亚洲热综合一本| 亚洲色欲色欱wwW在线|