AJAX——同源與跨域1

同源與跨域

1. 同源

同源策略的基本概念

1995年,同源政策由 Netscape 公司引入瀏覽器。目前,所有瀏覽器都實行這個政策。同源策略:最初,它的含義是指,A網頁設置的 Cookie,B網頁不能打開,除非這兩個網頁"同源"。所謂"同源"指的是"三個相同"。

協議相同
域名相同
端口相同

舉例來說,這個網址http://www.example.com/dir/page.html協議是http://

域名是www.example.com,端口是80(默認端口可以省略)。它的同源情況如下。

http://www.example.com/dir2/other.html:同源

file:///F:/phpStudy/WWW/day01/04-demo/04.html 不同源(協議不同)
http://v2.www.example.com/dir/other.html:不同源(域名不同)
http://www.example.com:81/dir/other.html:不同源(端口不同)

同源策略的目的

同源政策的目的,是爲了保證用戶信息的安全,防止惡意的網站竊取數據。

同源策略的限制範圍

隨着互聯網的發展,“同源策略”越來越嚴格,目前,如果非同源,以下三種行爲都將收到限制。

1. Cookie、LocalStorage 和 IndexDB 無法讀取。
2. DOM 無法獲得。
3. AJAX 請求不能發送。

雖然這些限制是很有必要的,但是也給我們日常開發帶來不好的影響。比如實際開發過程中,往往都會把服務器端架設到一臺甚至是一個集羣的服務器中,把客戶端頁面放到另外一個單獨的服務器。那麼這時候就會出現不同源的情況,如果我們知道兩個網站都是安全的話,我們是希望兩個不同源的網站之間可以相互請求數據的。這就需要使用到跨域

2. 跨域

jsonp( 無兼容性問題 )

JSONP(JSON with Padding)、可用於解決主流瀏覽器的跨域數據訪問的問題。

原理:服務端返回一個定義好的js函數的調用,並且將服務器的數據以該函數參數的形式傳遞過來,這個方法需要前後端配合

script 標籤是不受同源策略的限制的,它可以載入任意地方的 JavaScript 文件。類似的還有imglink標籤

<!--不受同源策略限制的標籤-->
<img src="http://www.api.com/1.jpg" alt="">
<link rel="stylesheet" href="http://www.api.com/1.css">
<script src="http://www.api.com/1.js"></script>

jsonp演化過程1

php文件

header("content-type:text/html;charset=utf-8");
echo "alert(1111)";

html文件

<script src="http://www.api.com/testjs.php"></script>

原理:其實src的路徑是什麼文件不重要,無論引入js文件還是php文件,最後返回給瀏覽器的都是字符串,因此我們script標籤是可以引入一個php文件的。

jsonp演化過程2

php文件

header("content-type:text/html;charset=utf-8");
echo "var a = 118;";

html文件

<script src="http://www.api.com/testjs.php"></script>
<script>
  //a打印出來了118
  console.log(a);
</script>

我們現在做到了一件事情,從不同源的php文件中獲取到了數據

缺點:獲取數據的script標籤必須寫在使用的script標籤的前面,必須保證先有數據才能對數據進行渲染。

jsonp演化過程3

php代碼

header("content-type:text/html;charset=utf-8");
$arr = array(
    "name"=>"zs",
    "age"=>18
);
$result = json_encode($arr);
//這是一段js函數的調用的代碼,$result就是我們想要的數據
echo "func($result)";

js代碼

<script>
  function func(data) {
    console.log(data);
  }
</script>
<script src="http://www.api.com/testjs.php"></script>

缺點:後端必須知道前端聲明的方法的名字,後端才能調用。

jsonp演化過程4

php代碼

header("content-type:text/html;charset=utf-8");
$arr = array(
    "name"=>"zs",
    "age"=>18
);
$result = json_encode($arr);
//這是一段js函數的調用的代碼,$result就是我們想要的數據
echo $_GET['callback']."($result)";
// jsonp: json width padding  
//echo "$callback($result)";

javascript代碼

function fun(data) {
  console.log(data);
}
var button = document.querySelector("button");
button.onclick = function () {
  var script = document.createElement("script");
  script.src = "http://www.api.com/testjs.php?callback=fun";
  document.body.appendChild(script);
}
  1. jsonp的原理就是 藉助了script標籤 src 請求資源時, 不受同源策略的限制.

  2. 在服務端返回一個函數的調用,將數據當前調用函數的實參。

  3. 在瀏覽器通過形端,需要程序要聲明一個全局函數,參就可以獲取到服務端返回的對應的值

jquery對於jsonp的封裝

//使用起來相當的簡單,跟普通的get請求沒有任何的區別,只需要把dataType固定成jsonp即可。
$.ajax({
  type:"get",
  url:"http://www.Jepson.com/testjs.php",
  dataType:"jsonp",
  data:{
    uname:"Jepson",
    upass:"123456"
  },
  success:function (info) {
    console.log(info);
  }
});

【案例:查詢天氣.html】 [天氣查詢api地址](https://www.jisuapi.com/api/weather/)

【案例:省市區三級聯動.html】 api地址 (https://www.jisuapi.com/api/area/)

//天氣.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    table {
      margin-top: 20px;
      width: 500px;
      border: 1px solid #000;
      border-collapse: collapse;
    }
    td {
      height: 30px;
      line-height: 30px;
      border: 1px solid #000;
    }
  </style>
</head>
<body>

<input type="text" id="city">
<input type="button" value="查詢" id="btn">

<table id="showTable">

</table>


<script src="template-web.js"></script>
<script src="jquery-1.12.4.js"></script>

<script type="text/html" id="tpl">
  <tr>
    <td>城市</td>
    <td>{{ result.city }}</td>
  </tr>
  <tr>
    <td>日期</td>
    <td>{{ result.date }}</td>
  </tr>
  <tr>
    <td>天氣</td>
    <td>{{ result.weather }}</td>
  </tr>
  <tr>
    <td>氣溫</td>
    <td>{{ result.temp }}度</td>
  </tr>
  <tr>
    <td>最高氣溫</td>
    <td>{{ result.temphigh }}度</td>
  </tr>
  <tr>
    <td>最低氣溫</td>
    <td>{{ result.templow }}度</td>
  </tr>
  <tr>
    <td>更新時間</td>
    <td>{{ result.updatetime }}</td>
  </tr>
</script>


<script>
  // 思路: 1. 點擊按鈕, 獲取文本框的內容, 發送 jsonp 請求(跨域了), 請求數據, 
  //       2. 得到數據, 通過模板引擎來渲染

  $(function() {
    
    $('#btn').click(function() {

      $.ajax({
        type: "get",
        url: "http://api.jisuapi.com/weather/query",
        data: {
          appkey: "3fa977031a30ffe1",
          city: $('#city').val()
        },
        dataType: "jsonp",
        success: function( info ) {
          console.log( info )
          // 模板 id, 數據對象
          var htmlStr = template( "tpl", info );
          $('#showTable').html( htmlStr );
        }
      });

    });

  })
</script>
</body>
</html>
//省市區.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    div {
      margin: 50px;
    }
  </style>
</head>
<body>


<div>
  <select id="s1">
    <option>請選擇</option>
  </select>
  <select id="s2">
    <option>請選擇</option>
  </select>
  <select id="s3">
    <option>請選擇</option>
  </select>
</div>


<script src="jquery-1.12.4.js"></script>
<script src="template-web.js"></script>

<script type="text/html" id="tpl">
  <option>請選擇</option>
  {{ each result v i }}
    <option value="{{ v.id }}">{{ v.name }}</option>
  {{ /each }}
</script>

<script>
  // 兩個核心點
  // 1. 監聽 select 變化, 用change
  // 2. 獲取選中的內容 id, 通過 select 的 value 來獲取
  
  // 思路:
  // 1. 一進入頁面, 請求省的數據
  // 2. 用戶選擇了省, 請求市的數據
  // 3. 用戶選擇了市, 請求區的數據
  $.ajax({
    type: "get",
    url: "http://api.jisuapi.com/area/province",
    data: {
      appkey: "3fa977031a30ffe1"  // 用戶唯一標識, 每個人的個人中心可以查看
    },
    dataType: "jsonp",
    success: function( info ) {
      console.log( info );
      var htmlStr = template( "tpl", info );
      $('#s1').html( htmlStr );
    }
  });

  // change 事件, 當select被選擇的內容改變時觸發
  $('#s1').change(function() {
    // 重置市和區的數據
    $('#s2').html("<option>請選擇</option>");
    $('#s3').html("<option>請選擇</option>");
    // console.log( "選擇的內容改變了" );
    // 發送 ajax 請求, 請求市的數據
    $.ajax({
      type: "get",
      url: "http://api.jisuapi.com/area/city",
      data: {
        parentid: $('#s1').val(),    // 獲取選中的省的 id
        appkey: "3fa977031a30ffe1"
      },
      dataType: "jsonp",
      success: function( info ) {
        var htmlStr = template( "tpl", info );
        $('#s2').html( htmlStr );
      }
    })
  });

  $('#s2').change(function() {
    // 發送ajax請求, 獲取區的數據
    $.ajax({
      type: "get",
      url: "http://api.jisuapi.com/area/town",
      data: {
        parentid: $('#s2').val(),    // 獲取選中的城市 id
        appkey: "3fa977031a30ffe1"
      },
      dataType: "jsonp",
      success: function( info ) {
        var htmlStr = template( "tpl", info );
        $('#s3').html( htmlStr );
      }
    })
  })  
</script>
</body>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章