天天看點

jsonp解決跨域問題1. 原理分析2. JSONP方案具體實作

JSONP解決跨域問題

  • 1. 原理分析
    • 1.1 同源政策
    • 1.2 跨域的情形
    • 1.3 跨域問題的解決方案
    • 1.4 什麼是JSONP
  • 2. JSONP方案具體實作
    • 2.1動态建立script标簽
    • 2.2 用jQuery中$.getJSON()實作JSONP
    • 2.3 用jQuery中$.ajax()實作JSONP
    • 2.4 總結:

最近在學習ajax跨域的問題,為了加深了解,寫篇部落格記錄一下。

1. 原理分析

1.1 同源政策

我們先來看看跨域問題涉及的一些概念:

  • 源: 指頁面中資料的來源,由三部分指定:協定名、域名或IP位址、端口号
  • 同源政策:不同源的用戶端js腳本在沒有明确授權的情況下,不能讀寫對方資源(a.com下的js腳本采用ajax不能讀取b.com裡面的檔案資料,會發生跨域錯誤)
  • 跨域錯誤:(如下圖)
    jsonp解決跨域問題1. 原理分析2. JSONP方案具體實作

1.2 跨域的情形

jsonp解決跨域問題1. 原理分析2. JSONP方案具體實作

上圖中有“紅色标記”的栗子都是不同源的情形。總的來說,協定名、域名、端口号任意一項不同就不同源。

1.3 跨域問題的解決方案

  • 很多項目中,為了實作前後端分離,會特意将前端靜态資源(html/css/js等)與背景資料接口 分處在不同的伺服器上,是以域名/ip或端口号必然不相同,這就導緻了“跨域請求問題”。
  • 跨域問題的解決方案有:

    – 代理請求

    –JSONP

    –CORS

本文主要将jsonp方案解決跨域問題,其他方案學習透徹了再來總結。

1.4 什麼是JSONP

  • JSONP(json with padding)是json的一種使用模式。
  • 通過上面的學習,我們已經知道,由于同源政策浏覽器會禁止JS跨域。

    但是,我們知道script标簽是允許跨域請求的。利用這個特性,用戶端使用script代替XHR( XMLHttpRequest)發起跨域請求,伺服器在json響應資料前後填充一些額外的内容,就稱為“填充式JSON”——JSONP

2. JSONP方案具體實作

JSONP實作跨域請求的原理就是動态建立script标簽,利用“src”不受同源政策限制的性質來實作跨域擷取資料。

菜鳥教程提供了一個連結,我們可以用它練練手~

連結:https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction

2.1動态建立script标簽

下面栗子很簡單,就不細說了~

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JSONP 執行個體</title>
</head>
<body>
<script>
  function callbackFunction(data){
    console.log("i got it");
    console.log(data);
  }
</script>
<script>
  window.onload=function(){
    var script=document.createElement("script");
    script.src="https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction";
    document.head.append(script);
  }
</script>
</body>
</html>
           

2.2 用jQuery中$.getJSON()實作JSONP

  • $.getJSON()方法允許通過使用JSONP形式的回調函數來加載其他網域的JSON資料
  • 使用$.getJSON()方法實作跨域請求,需要在請求路徑URL後增加callback=?, jQuery将自動替換“?”為正确的函數名,以執行回調函數。

注:下面代碼中路徑後是jsoncallback=?,因為服務端的代碼中回調函數名為jsoncallback,前後端應該是一緻的

記得引入jQuery檔案!

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JSONP 執行個體</title>
    <script src="https://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js"></script>    
</head>
<body>
<script>
$.getJSON("https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=?",function(data){console.log(data);})
</script>
</body>
</html>
           

2.3 用jQuery中$.ajax()實作JSONP

$.ajax()方法同樣可以實作JSONP跨域請求,我們主要來看看它的一些選項參數:

  • url:請求位址
  • type:請求方式
  • dataType:“jsonp” 必寫,設定伺服器端傳回的資料類型,這裡是"jsonp"
  • jsonp:獲得jsonp回調函數名的參數名,這個值用于代替"callback=?"(本例就是用"jsoncallback=?“代替了"callback=?”),一般預設都是callback
  • jsonCallback:可選,為JSONP請求指定一個回調函數名,這個值将代替jQuery自動生成的随機函數名(就是代替"callback=?"中的問号)
  • success:請求成功後的回調函數。

知道這些選項參數的意思了,我們再看看上面給到的那個連結:

https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction

我們看到調用的url中,jsoncallback參數告訴伺服器,我的本地回調函數叫做callbackFunction,讓伺服器請把查詢結果傳入這個函數中。伺服器傳遞給callbackFunction函數json格式的資料:callbackFunction([“customername1”,“customername2”])

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JSONP 執行個體</title>
    <script src="https://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js"></script>    
</head>
<body>
<script>
$.ajax({
  url: "https://www.runoob.com/try/ajax/jsonp.php",
  type: "get",
  dataType: "jsonp",
  jsonp: "jsoncallback",
  success: function(data){
    console.log(data);
  }
})
</script>
</body>
</html>
           

2.4 總結:

  • ajax和jsonp本質上是不同的東西。ajax的核心是通過XmlHttpRequest擷取非本頁内容,而jsonp的核心則是動态添加script标簽來調用伺服器提供的js腳本。
  • JSONP方案屬于用戶端直接請求,不存在二次請求的問題;但是,不足是script标簽隻能發起get請求。

繼續閱讀