99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋(píng)果6袋
6
麥子學(xué)院

Javascript學(xué)習(xí)之跨域詳解

發(fā)布時(shí)間:2017-02-27 18:26  回復(fù):0  查看:2193   最后回復(fù):2017-02-27 18:26  

在客戶(hù)端編程語(yǔ)言中如javascript,同源策略規(guī)定跨域之間的腳本是隔離的,一個(gè)域的腳本不能訪問(wèn)和操作另外一個(gè)域的絕大部分屬性和方法。只有當(dāng)兩個(gè)域具有相同的協(xié)議,相同的主機(jī),相同的端口時(shí),我們就認(rèn)定他們是相同的域??墒窃趯?shí)際開(kāi)發(fā)中我們經(jīng)常需要獲取其他域的資源,這個(gè)時(shí)候各種不同的跨域資源方式就各顯神通了,今天主要來(lái)總結(jié)一下工作中常用的幾種跨域方式,以備查詢(xún)。一起來(lái)看看吧,希望對(duì)大家學(xué)習(xí)javascript有所幫助。

  1.window.name

  window 對(duì)象的name屬性是一個(gè)很特別的屬性,當(dāng)在 frame 中加載新頁(yè)面時(shí),name 的屬性值依舊保持不變。那么我們可以在頁(yè)面 A中用iframe加載其他域的頁(yè)面B,而頁(yè)面B中用JavaScript把需要傳遞的數(shù)據(jù)賦值給window.name,iframe加載完成之后,此時(shí) name 屬性值可被獲取到,以訪問(wèn) Web 服務(wù)發(fā)送的信息。但 name 屬性?xún)H對(duì)相同域名的 frame 可訪問(wèn)。這意味著為了訪問(wèn) name 屬性,當(dāng)遠(yuǎn)程 Web 服務(wù)頁(yè)面被加載后,必須導(dǎo)航 frame 回到原始域。即頁(yè)面A修改iframe的地址,將其變成同域的一個(gè)地址,然后就可以讀出window.name的值了。一旦 name 屬性獲得,銷(xiāo)毀 frame 。這個(gè)方式非常適合單向的數(shù)據(jù)請(qǐng)求,而且協(xié)議簡(jiǎn)單、安全。

  頁(yè)面B(www.jesse.com/data.html)代碼如下:

  <script type="text/javascript">window.name = 'I was there!';// 這里是要傳輸?shù)臄?shù)據(jù),大小一般為2MIEfirefox下可以大至32M左右// 數(shù)據(jù)格式可以自定義,如json、字符串script>

  頁(yè)面A(www.jack.com/index.html)代碼如下:

  <script type="text/javascript">var state = 0,

  iframe = document.('iframe'),

  loadfn = function() {

  if (state === 1) {

  var data = iframe.contentWindow.name; // 讀取數(shù)據(jù)

  console.log(data); //彈出'I wasthere!'

  (function(){

  //獲取數(shù)據(jù)以后銷(xiāo)毀這個(gè)iframe。

  iframe.contentWindow.document.write('');

  iframe.contentWindow.close();

  document.body.removeChild(iframe);

  })();

  } else if (state === 0) {

  state = 1;

  // 設(shè)置的代理頁(yè)面使其回原始域

  iframe.contentWindow.location = "http://www.jack.com/proxy.html";;

  }

  };

  iframe.src = 'http://www.jesse.com/data.html';if (iframe.attachEvent) {

  iframe.attachEvent('onload', loadfn);

  } else {

  iframe.onload = loadfn;

  }document.body.appendChild(iframe);script>

  2.具備src的標(biāo)簽

  雖然瀏覽器默認(rèn)禁止了跨域訪問(wèn),但并不禁止在頁(yè)面中用標(biāo)簽的src屬性引用其他域的文件。根據(jù)這一點(diǎn),可以方便地通過(guò)創(chuàng)建具有src屬性的節(jié)點(diǎn)方法來(lái)實(shí)現(xiàn)完全跨域的通信。使用這種原理的跨域方式有以下幾種:

  動(dòng)態(tài)創(chuàng)建script

  例如我要從域A的頁(yè)面pageA加載域B的數(shù)據(jù),那么在域B的頁(yè)面pageB中我以JavaScript的形式聲明pageA需要的數(shù)據(jù),然后在 pageA中用script標(biāo)簽把pageB加載進(jìn)來(lái),那么pageB中的腳本就會(huì)得以執(zhí)行。

  pageA(www.jack.com/index.html)代碼如下:

  function getData(data){

  //這里是對(duì)獲取的數(shù)據(jù)的相關(guān)操作

  console.log(data);

  //數(shù)據(jù)獲取到后移除創(chuàng)建的script標(biāo)簽

  document.body.removeChild(originData);

  }var originData = document.('script');

  originData.src = 'http://www.jesse.com/data.js';

  originData.setAttribute("type", "text/javascript");document.body.appendChild(originData);

  pageB(www.jesse.com/data.js)代碼如下:

  getData('這里是遠(yuǎn)程跨域獲取的數(shù)據(jù)');//數(shù)據(jù)格式可以自定義,如json、字符串

  jsonp

  在用$.ajax()獲取遠(yuǎn)程數(shù)據(jù)時(shí),如果是跨域資源則可以使用jsonp方法,以前一直以為jsonpajax的一種,后來(lái)才明白他們根本就不是一回事。ajax是以xhr方式請(qǐng)求數(shù)據(jù)的,而jsonp是以script方式請(qǐng)求數(shù)據(jù)的,這個(gè)就是和上面的動(dòng)態(tài)創(chuàng)建script方式一樣。

  pageA(www.jack.com/index.html)代碼如下:

  $.ajax({

  //JSONP不支持POST方式

  type:"GET",

  url:"http://www.jesse.com/data.php";,

  dataType:"jsonp",

  //自定義的jsonp回調(diào)函數(shù)名稱(chēng),默認(rèn)為jQuery自動(dòng)生成的隨機(jī)函數(shù)名,也可以寫(xiě)"?"jQuery會(huì)自動(dòng)為你處理數(shù)據(jù)

  jsonpCallback:"getData",

  success: function(data){

  console.log(data);

  },

  error: function(){

  console.log('fail');

  }

  })

  pageB(www.jesse.com/data.js)代碼如下:

  <?php

  $callback = $_GET['callback'];//得到回調(diào)函數(shù)名,這里是getData

  $data = array('a','b','c');//要返回的數(shù)據(jù)

  echo $callback.'('.json_encode($data).')';//輸出?>

  3.document.domain

  對(duì)于主域相同而子域不同的例子,可以通過(guò)設(shè)置document.domain的辦法來(lái)解決。 具體的做法是可以在http://www.a.com/a.htmlhttp://script.a.com/b.html兩個(gè)文件中分別加上 document.domain = "a.com";然后通過(guò)a.html文件中創(chuàng)建一個(gè)iframe,去控制iframecontentDocument,這樣兩個(gè)js文件之間就可以 交互了。當(dāng)然這種辦法只能解決主域相同而二級(jí)域名不同的情況

  www.a.com上的a.html

  document.domain = 'a.com';var ifr = document.('iframe');

  ifr.src = 'http://script.a.com/b.html';

  ifr.style.display = 'none';document.body.appendChild(ifr);

  ifr.onload = function(){

  var doc = ifr.contentDocument || ifr.contentWindow.document;

  // 在這里操縱b.html

  alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);

  };

  script.a.com上的b.html

  document.domain = 'a.com';

  4.跨域資源共享(CORS

  原理:跨源資源共享(CORS)定義一種跨域訪問(wèn)的機(jī)制,可以讓AJAX實(shí)現(xiàn)跨域訪問(wèn)。CORS允許一個(gè)域上的網(wǎng)絡(luò)應(yīng)用向另一個(gè)域提交跨域AJAX請(qǐng)求。實(shí)現(xiàn)此功能非常簡(jiǎn)單,只需由服務(wù)器發(fā)送一個(gè)響應(yīng)標(biāo)頭即可。它是通過(guò)客戶(hù)端+服務(wù)端協(xié)作聲明的方式來(lái)確保請(qǐng)求安全的。服務(wù)端會(huì)在HTTP請(qǐng)求頭中增加一系列HTTP請(qǐng)求參數(shù)(例如Access-Control-Allow-Origin),來(lái)限制哪些域的請(qǐng)求和哪些請(qǐng)求類(lèi)型可以接受,而客戶(hù)端在發(fā)起請(qǐng)求時(shí)必須聲明自己的源(Orgin),否則服務(wù)器將不予處理,如果客戶(hù)端不作聲明,請(qǐng)求甚至?xí)粸g覽器直接攔截都到不了服務(wù)端。服務(wù)端收到HTTP請(qǐng)求后會(huì)進(jìn)行域的比較,只有同域的請(qǐng)求才會(huì)處理。

  pageA(www.jack.com/index.html)代碼如下:

  var xhr = new XMLHttpRequest();

  xhr.onreadystatechange = function(){

  if(xhr.readyState === 4 && xhr.status === 200){

  console.log(xhr.responseText);

  }

  };

  xhr.open("get","http://www.jesse.com/data.php";);

  xhr.send(null);

  pageB(www.jesse.com/data.php)代碼如下:

  <?php

  header("Access-Control-Allow-Origin: http://www.jack.com";);//與簡(jiǎn)單的請(qǐng)求相同

  header("Access-Control-Allow-Methods: GET, POST");//允許請(qǐng)求的方法

  header("Access-Control-Max-Age: 3628800"); //將這個(gè)請(qǐng)求緩存多長(zhǎng)時(shí)間

  $data = array('a','b','c');//要返回的數(shù)據(jù)

  echo json_encode($data);//輸出?>

  5.window.postMesage 不常用

  window.postMessage(message,targetOrigin) 方法是html5新引進(jìn)的特性,可以使用它來(lái)向其它的window對(duì)象發(fā)送消息,無(wú)論這個(gè)window對(duì)象是屬于同源或不同源,目前IE8+、FireFox、Chrome、Opera等瀏覽器都已經(jīng)支持window.postMessage方法。

  pageA(www.jack.com/index.html)代碼如下:

  <iframe id="proxy" src="http://www.jesse.com/index.html"; onload="postMsg()" style="display: none">iframe><script type="text/javascript">var obj = {

  msg: 'hello world'

  }

  function postMsg() {

  var iframe = document.getElementById('proxy');

  var win = iframe.contentWindow;

  win.postMessage(obj, 'http://www.jesse.com');

  }script>

  pageB(www.jesse.com/data.php)代碼如下:

  <script type="text/javascript">window.onmessage = function(e) {

  console.log(e.data.msg + " from " + e.origin);

  }script>

  6. location.hash 不常用

  pageA(www.jack.com/index.html)代碼如下:

  function startRequest() {

  var ifr = document.('iframe');

  ifr.style.display = 'none';

  ifr.src = 'http://www.jesse.com/b.html#sayHi'; //傳遞的location.hash

  document.body.appendChild(ifr);

  }

  function checkHash() {

  try {

  var data = location.hash ? location.hash.substring(1) : '';

  if (console.log) {

  console.log('Now the data is ' + data);

  }

  } catch (e) {};

  }

  setInterval(checkHash, 5000);window.onload = startRequest;

  pageA(www.jack.com/proxy.html)代碼如下:

  parent.parent.location.hash = self.location.hash.substring(1);

  pageB(www.jesse.com/b.html)代碼如下:

  function checkHash() {

  var data = '';

  //模擬一個(gè)簡(jiǎn)單的參數(shù)處理操作

  switch (location.hash) {

  case '#sayHello':

  data = 'HelloWorld';

  break;

  case '#sayHi':

  data = 'HiWorld';

  break;

  default:

  break;

  }

  data && callBack('#' + data);

  }

  function callBack(hash) {

  // ie、chrome的安全機(jī)制無(wú)法修改parent.location.hash,所以要利用一個(gè)中間的www.a.com域下的代理iframe

  var proxy = document.('iframe');

  proxy.style.display = 'none';

  proxy.src = 'http://www.jack/c.html' + hash; // 注意該文件在"www.jack.com";域下

  document.body.appendChild(proxy);

  }window.onload = checkHash;

 

 

來(lái)源:博客園

您還未登錄,請(qǐng)先登錄

熱門(mén)帖子

最新帖子

?