跨域方法總結(一),JSONP

前言

博主博客:Stillwater的博客
知乎專欄:前端汪汪
本文爲做者原創轉載請註明出處:http://hiztx.top/2017/01/15/j...javascript


  本文介紹了什麼是跨域,爲何要跨域,以及跨域的一種經常使用方法JSONP的原理。php

1、什麼是跨域?爲何要跨域?

什麼是跨域?

  既然是跨域,那麼確定是從一個域到另外一個域。那麼首先要知道知足什麼條件纔是同一個域。若是兩個頁面擁有相同的協議,端口和域名,那麼這兩個頁面就屬於同一個源(origin),JavaScript容許這種同源頁面的數據互相通訊。例如你要訪問百度首頁html

https://www.baidu.com
https是協議
https協議的默認端口爲443(不顯示)
www.baidu.com爲域名前端

注:通常端口默認爲不顯示,可是你能夠嘗試輸入如下網址,發現沒法訪問。由於80端口默認爲http協議端口。java

https://www.baidu.com:80git

  如今知道了什麼是同一個域,那麼就能夠解釋什麼是跨域。只要協議、域名、端口有任何一個不一樣,都被看成是不一樣的域,之間的請求就是跨域操做。github

爲何要跨域?

  相信不少人都聽過,同源策略。出於安全考慮,瀏覽器對JavaScript的不少功能進行了限制,其中一條就是,不一樣域之間不予許進行數據通訊。雖然補全了安全漏洞,可是這個限制給前端開發帶來了許多不便。例如:web

zhidao.baidu.com
wenku.baidu.comjson

  百度知道和百度文庫你們都不陌生,都是百度開發的web服務。雖然這兩個都是李彥宏的,可是如今告訴他,因爲你這兩個域名的三級域名不同,不容許相互數據通訊。你說不行就不行?因而就有像李彥宏這樣的大牛搞出一些黑科技專門用來跨域通訊。JSONP就是其中之一。segmentfault

注:
1.com爲頂級域名,baidu爲二級域名,zhidao/wenku爲三級域名
2.跨域並不是瀏覽器限制了發起跨站請求,而是跨站請求能夠正常發起,但返回結果被瀏覽器攔截了。

2、什麼是JSONP?

顧名思義:

JSONP = JSON + P

  JSONP(JSON with Padding),JSON是一種輕量級的數據交換格式。而Padding在這裏能夠翻譯爲填充。那麼JSONP的意思就是,填充的JSON。是數據格式JSON的一種使用模式,可讓網頁從別的網域要數據。

3、JSONP原理

JSONP的核心原理就是,HTML的script標籤能夠加載並執行其餘域JS文件。

  這裏區分兩個概念,當咱們用瀏覽器打開百度知道首頁的時候,是向百度知道服務器發送了一個Https請求,獲取到百度知道首頁的index.html。若是在這個index.html裏面用XMLHttpRequest對象向百度文庫服務器發送Https請求,那麼就屬於跨域,是不容許的。可是若是在百度知道首頁的index.html中加入一個script標籤,其src屬性指向百度文庫中的一個.json文件,是容許的。
  爲了理解這種模式的原理,先想像有一個回傳JSON文件的URL,而JavaScript 程序能夠用XMLHttpRequest跟這個URL要數據。假設咱們的URL是 http://server2.example.com/Re... 。假設小明的UserId 是1823,且當瀏覽器經過URL傳小明的UserId,也就是抓取 http://server2.example.com/Re... 。獲得:

{"Name": "小明",
 "Id": 1823,
 "Rank": 7
}

  這個JSON數據多是依據傳過去URL的查詢參數動態產生的。這個時候,把 script元素的src屬性設成一個回傳JSON的URL是能夠想像的,這也表明從HTML頁面經過script元素抓取JSON是可能的。然而,一份JSON文件並非一個JavaScript程序。爲了讓瀏覽器能夠在 script元素運行,從src裏URL回傳的必須是可運行的JavaScript。在JSONP的使用模式裏,該URL回傳的是由函數調用包起來的動態生成JSON,這就是JSONP的「填充(padding)」或是「前輟(prefix)」的由來。

<script type="text/javascript"
         src="http://server2.example.com/RetrieveUser?UserId=1823&jsonp=parseResponse">
 </script>

  服務器會在傳給瀏覽器前將JSON數據填充到回調函數(parseResponse)中。瀏覽器獲得的迴應已不是單純的數據敘述而是一個腳本。在本例中,瀏覽器獲得的是:

{
    parseResponse(
        {
         "Name": "小明",
         "Id": 1823,
         "Rank": 7
         })
}

  也就是說,通常狀況下瀏覽器向服務器發送請求獲得的都是數據(文本,XML,JSON),可是當採用JSONP技術時候,瀏覽器向跨域服務器發送請求,獲得的是回調函數包住的JSON。此處JSON做爲參數傳入回調函數,而後再返回給瀏覽器。

再舉個例子:

瀏覽器端:

<body>
  <!--聲明jsonpcallback回調函數,參數爲json數據-->
  <script type="text/javascript">
    function jsonpcallback(json) {
      console.log(json);
    }
    
    <!--建立一個<script>標籤,設置src爲一個跨域的URL,並指定回調函數爲jsonpcallback-->
    var s = document.createElement('script');
    s.src="http://localhost:8080/test.php?callback=jsonpcallback";
    document.body.appendChild(s);
  </script>
</body>

服務器端:

<?php
  $jsondata = '{
    "name": "Stillwater",
    "age": 12
  }';
  echo $_GET['callback'].'('.$jsondata.')';
?>

服務器返回瀏覽器:

jsonpcallback(
    {
        "name": "Stillwater",
        "age": 12
    }
    )

  在這個例子中,瀏覽器向服務器發出跨域請求 http://localhost:8080/test.ph... 。請求一個json數據, {"name": "Stillwater","age": 12} 。而且告訴了服務器回調函數的名字。服務器接收到請求後,就將json數據做爲參數填充到回調函數中,返回給瀏覽器。最終返回一個填充了json數據的回調函數。

4、總結

  1. 首先在客戶端註冊一個callback,而後把callback的名字傳給服務器。

  2. 服務器先生成json數據。而後以Javascript語法的方式,生成一個function ,function名字就是傳遞上來的參數callback。 最後將json數據直接以入參的方式,放置到function中,這樣就生成了一段 js 語法的文檔,返回給客戶端。

  3. 客戶端瀏覽器,解析script標籤,並執行返回的Javascript 文檔,此時數據做爲參數,傳入到了客戶端預先定義好的callback 函數裏。(動態執行回調函數)

參考連接:

https://zh.wikipedia.org/wiki...
http://www.cnblogs.com/zichi/...
http://tech.jandou.com/cross-...
https://segmentfault.com/a/11...
http://wearejq.github.io/2015...

相關文章
相關標籤/搜索