最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解ajax跨域問題解決方案

 更新時間:2017年06月21日 08:34:07   作者:小城仲夏  
這篇文章主要介紹了詳解ajax跨域問題解決方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

今天來記錄一下關(guān)于ajax跨域的一些問題。以備不時之需。

跨域

同源策略限制

同源策略阻止從一個域上加載的腳本獲取或操作另一個域上的文檔屬性。也就是說,受到請求的 URL 的域必須與當(dāng)前 Web 頁面的域相同。這意味著瀏覽器隔離來自不同源的內(nèi)容,以防止它們之間的操作。

解決方式

通常來說,比較通用的有如下兩種方式,一種是從服務(wù)器端下手,另一種則是從客戶端的角度出發(fā)。二者各有利弊,具體要使用哪種方式還需要具體的分析。

  1. 服務(wù)器設(shè)置響應(yīng)頭
  2. 服務(wù)器代理
  3. 客戶端采用腳本回調(diào)機(jī)制。

方式一

Access-Control-Allow-Origin 關(guān)鍵字只有在服務(wù)器端進(jìn)行設(shè)置才
會生效。也就是說即使再客戶端使用

xmlhttprequest.setHeaderREquest('xx','xx');

也不會有什么效果。

正常ajax請求

下面來模擬一下ajax非跨域請求的案例實現(xiàn)。

test1.html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>ajax 測試</title>
</head>
<body>

<input type="button" value="Test" onclick="crossDomainRequest()">
<div id="content"></div>
<script>
 var xhr = new XMLHttpRequest();
 var url = 'http://localhost/learn/ajax/test1.php';

 function crossDomainRequest() {
  document.getElementById('content').innerHTML = "<font color='red'>loading...</font>";
  // 延遲執(zhí)行
  setTimeout(function () {
   if (xhr) {
    xhr.open('GEt', url, true);
    xhr.onreadystatechange = handle_response;
    xhr.send(null);
   } else {
    document.getElementById('content').innerText = "不能創(chuàng)建XMLHttpRequest對象";
   }
  }, 3000);
 }

 function handle_response() {
  var container = document.getElementById('content');
  if (xhr.readyState == 4) {
   if (xhr.status == 200 || xhr.status == 304) {
    container.innerHTML = xhr.responseText;
   } else {
    container.innerText = '不能跨域請求';
   }
  }
 }
</script>

</body>
</html>

同級目錄下的test1.PHP內(nèi)容如下:

<?php

echo "It Works.";

?>

正常ajax請求

跨域請求

剛才是HTML文件和php文件都在Apache的容器下,所以沒有出現(xiàn)跨域的情形,現(xiàn)在把HTML文件放到桌面上,這樣再次請求PHP數(shù)據(jù)的話,就營造了這樣一個“跨域請求”了。

注意看瀏覽器的地址欄信息

再次進(jìn)行訪問,發(fā)現(xiàn)會出現(xiàn)下面的錯誤信息。

跨域出現(xiàn)了問題

針對這種情況,比較常見的一個操作就是設(shè)置Access-Control-Allow-Origin。

格式: Access-Control-Allow-Origin: domain.com/xx/yy.*

如果知道客戶端的域名或者請求的固定路徑,則最好是不使用通配符的方式,來進(jìn)一步保證安全性。如果不確定,那就是用*通配符好了。

后端開發(fā)語言為PHP的時候可以再文件開始處這么設(shè)置:

header("Access-Control-Allow-Origin: *");

如果是ASPX頁面的話,要這么設(shè)置(Java與之類似):

Response.AddHeader("Access-Control-Allow-Origin", "*");

這時,再次來訪問一下剛才的路徑。

服務(wù)器端跨域設(shè)置

服務(wù)器代理模式

這種方式應(yīng)該算是比較常用的,而且被廣泛采納的一個方式了。說代理有點太過于書面化了,其實就是傳話兒的。來舉個小例子:

小明喜歡三班一個叫小紅的女孩兒,但是不好意思去要人家的QQ,微信號。然后就托和自己班的女生–小蘭。來幫自己去要。所以小蘭就相當(dāng)于一個代理。幫助小明獲取原本不能直接獲取的小紅的聯(lián)系方式。

下面來舉個例子說明這個問題。

直接的跨域請求

修改一下剛才的URL即可,讓ajax直接去請求其他網(wǎng)站的數(shù)據(jù)。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>ajax 測試</title>
</head>
<body>

<input type="button" value="Test" onclick="crossDomainRequest()">
<div id="content"></div>
<script>
 var xhr = new XMLHttpRequest();
// var url = 'http://localhost/learn/ajax/test1.php';
  var url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E5%93%92%E5%93%92';
 function crossDomainRequest() {
  document.getElementById('content').innerHTML = "<font color='red'>loading...</font>";
  // 延遲執(zhí)行
  setTimeout(function () {
   if (xhr) {
    xhr.open('GEt', url, true);
    xhr.onreadystatechange = handle_response;
    xhr.send(null);
   } else {
    document.getElementById('content').innerText = "不能創(chuàng)建XMLHttpRequest對象";
   }
  }, 3000);
 }

 function handle_response() {
  var container = document.getElementById('content');
  if (xhr.readyState == 4) {
   if (xhr.status == 200 || xhr.status == 304) {
    container.innerHTML = xhr.responseText;
   } else {
    container.innerText = '不能跨域請求';
   }
  }
 }
</script>

</body>
</html>

結(jié)果如下:

代理模式下直接跨域會失敗

啟用代理模式

剛才的HTML頁面,咱們還是用自己的接口:

url = 'http://localhost/learn/ajax/test1.php';

具體如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>ajax 測試</title>
</head>
<body>

<input type="button" value="Test" onclick="crossDomainRequest()">
<div id="content"></div>
<script>
 var xhr = new XMLHttpRequest();
 var url = 'http://localhost/learn/ajax/test1.php';
//  var url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E5%93%92%E5%93%92';
 function crossDomainRequest() {
  document.getElementById('content').innerHTML = "<font color='red'>loading...</font>";
  // 延遲執(zhí)行
  setTimeout(function () {
   if (xhr) {
    xhr.open('GEt', url, true);
    xhr.onreadystatechange = handle_response;
    xhr.send(null);
   } else {
    document.getElementById('content').innerText = "不能創(chuàng)建XMLHttpRequest對象";
   }
  }, 3000);
 }

 function handle_response() {
  var container = document.getElementById('content');
  if (xhr.readyState == 4) {
   if (xhr.status == 200 || xhr.status == 304) {
    container.innerHTML = xhr.responseText;
   } else {
    container.innerText = '不能跨域請求';
   }
  }
 }
</script>

</body>
</html>

然后對應(yīng)的test1.php應(yīng)該幫助我們實現(xiàn)數(shù)據(jù)請求這個過程,把“小紅的聯(lián)系方式”要到手,并返回給“小明”。

<?php

$url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg=hello%20world.';
$result = file_get_contents($url);
echo $result;

?>

下面看下代碼執(zhí)行的結(jié)果。

代理模式下的跨域?qū)崿F(xiàn)

jsonp方式

JSONP(JSON with Padding) 靈感其實源于在HTML頁面中script標(biāo)簽內(nèi)容的加載,對于script的src屬性對應(yīng)的內(nèi)容,瀏覽器總是會對其進(jìn)行加載。于是:

克服該限制更理想方法是在 Web 頁面中插入動態(tài)腳本元素,該頁面源指向其他域中的服務(wù) URL 并且在自身腳本中獲取數(shù)據(jù)。腳本加載時它開始執(zhí)行。該方法是可行的,因為同源策略不阻止動態(tài)腳本插入,并且將腳本看作是從提供 Web 頁面的域上加載的。但如果該腳本嘗試從另一個域上加載文檔,就不會成功。

實現(xiàn)的思路就是:

在服務(wù)器端組裝出客戶端預(yù)置好的json數(shù)據(jù),通過回調(diào)的方式傳回給客戶端。

原生實現(xiàn)

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>ajax 測試</title>
 <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>
</head>
<body>
<input type="text" name="talk" id="talk">
<input type="button" value="Test" id="btn">
<div id="content"></div>
<script type="text/javascript">

function jsonpcallback(result) {
 for(var i in result) {
  alert(i+":"+result[i]);
 }
 }
 var JSONP = document.createElement("script");
 JSONP.type='text/javascript';
 JSONP.src='http://localhost/learn/ajax/test1.php?callback=jsonpcallback';
 document.getElementsByTagName('head')[0].appendChild(JSONP);


</script>

</body>
</html>

服務(wù)器端test1.php內(nèi)容如下:

<?php

$arr = [1,2,3,4,5,6];
$result = json_encode($arr);
echo "jsonpcallback(".$result.")";

?>

需要注意的是最后組裝的返回值內(nèi)容。

來看下最終的代碼執(zhí)行效果。

JSONP原生跨域?qū)崿F(xiàn)

JQuery方式實現(xiàn)

采用原生的JavaScript需要處理的事情還是蠻多的,下面為了簡化操作,決定采用jQuery來代替一下。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>ajax 測試</title>
 <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>
</head>
<body>
<input type="text" name="talk" id="talk">
<input type="button" value="Test" id="btn">
<div id="content"></div>

<script type="text/javascript">

 function later_action(msg) {
  var element = $("<div><font color='green'>"+msg+"</font><br /></div>");
  $("#content").append(element);
 }

 $("#btn").click(function(){
  // alert($("#talk").val());
  $.ajax({
  url: 'http://localhost/learn/ajax/test1.php',
  method: 'post',
  dataType: 'jsonp',
  data: {"talk": $("#talk").val()},
  jsonp: 'callback',
  success: function(callback){
   console.log(callback.content);
   later_action(callback.content);
  },
  error: function(err){
   console.log(JSON.stringify(err));

  },
 });
 });
</script>

</body>
</html>

相應(yīng)的,test1.php為了配合客戶端聊天的需求,也稍微做了點改變。

<?php
$requestparam = isset($_GET['callback'])?$_GET['callback']:'callback';

// 青云志聊天機(jī)器人接口: http://api.qingyunke.com/api.php?key=free&appid=0&msg=hello
// 接收來自客戶端的請求內(nèi)容
$talk = $_REQUEST['talk'];
$result = file_get_contents("http://api.qingyunke.com/api.php?key=free&appid=0&msg=$talk");

// 拼接一些字符串
echo $requestparam . "($result)";

?>

最后來查看一下跨域的效果吧。

JSONP 跨域?qū)崿F(xiàn)聊天應(yīng)用

總結(jié)

至此,關(guān)于簡單的ajax跨域問題,就算是解決的差不多了。對我個人而言,對于這三種方式有一點點自己的看法。

  1. 服務(wù)器設(shè)置Access-Control-Allow-Origin的方式適合信用度高的小型應(yīng)用或者個人應(yīng)用。
  2. 代理模式則比較適合大型應(yīng)用的處理。但是需要一個統(tǒng)一的規(guī)范,這樣管理和維護(hù)起來都會比較方便。
  3. JSONP方式感覺還是比較雞肋的(有可能是我經(jīng)驗還不足,沒認(rèn)識到這個方式的優(yōu)點吧(⊙﹏⊙)b)。自己玩玩知道有這么個東西好了。維護(hù)起來實在是優(yōu)點麻煩。

參考鏈接:

Ajax跨域請求: http://m.fzitv.net/article/72703.htm

服務(wù)器端跨域設(shè)置: http://m.fzitv.net/article/104442.htm

Ajax高級筆記: http://m.fzitv.net/article/116878.htm

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • jquery ajax實現(xiàn)批量刪除具體思路及代碼

    jquery ajax實現(xiàn)批量刪除具體思路及代碼

    回調(diào)函數(shù),在請求完成后需要進(jìn)行的操作:此處是把選中的checkbox去掉,接下來為大家詳細(xì)介紹下,感興趣的朋友可以參考下哈,希望對你有所幫助
    2013-04-04
  • Ajax添加數(shù)據(jù)即時顯示信息篇

    Ajax添加數(shù)據(jù)即時顯示信息篇

    經(jīng)過前3篇的ajax實例教程的學(xué)習(xí),我想各位已經(jīng)能夠使用ajax技術(shù)進(jìn)行簡單的數(shù)據(jù)讀取工作.
    2010-10-10
  • 淺談Ajax和JavaScript的區(qū)別

    淺談Ajax和JavaScript的區(qū)別

    下面小編就為大家?guī)硪黄獪\談Ajax和JavaScript的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • ajax后臺處理返回json值示例代碼

    ajax后臺處理返回json值示例代碼

    很多的新手朋友們不知道ajax如何處理返回json值,在本文將為大家詳細(xì)介紹下
    2013-09-09
  • Ajax的原生實現(xiàn)關(guān)于MIME類型的使用方法

    Ajax的原生實現(xiàn)關(guān)于MIME類型的使用方法

    下面小編就為大家分享一篇Ajax的原生實現(xiàn)關(guān)于MIME類型的使用方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • AJAX淺析數(shù)據(jù)交換的實現(xiàn)

    AJAX淺析數(shù)據(jù)交換的實現(xiàn)

    在AJAX中,最常用的就是JSON,XML因為比較冗雜所以用的比較少。所以我們先來說基于JSON的數(shù)據(jù)交換。最后我們還會提到在數(shù)據(jù)交換中出現(xiàn)亂碼的形式
    2022-08-08
  • 用Ajax讀取xml文件的簡單例子

    用Ajax讀取xml文件的簡單例子

    Ajax的原理很簡單,就是在客戶端創(chuàng)建一個XMLHttpRequest對象(用來與服務(wù)器進(jìn)行異步通信,這就是Ajax的核心,其實我們早就在用異步通信了,只是沒把這項技術(shù)用在網(wǎng)頁設(shè)計中而已),為該對象的onreadystatechange 屬性添加一個事件,當(dāng)對象的readyState改變的時候就會引發(fā)指定的事件。
    2008-04-04
  • Ajax的使用四大步驟

    Ajax的使用四大步驟

    ajax(異步j(luò)avascript xml) 能夠刷新局部網(wǎng)頁數(shù)據(jù)而不是重新加載整個網(wǎng)頁。接下來通過本文給大家介紹Ajax的使用四大步驟,非常不錯,感興趣的朋友看下吧
    2016-07-07
  • Ajax獲得站點文件內(nèi)容實例不涉及服務(wù)器

    Ajax獲得站點文件內(nèi)容實例不涉及服務(wù)器

    選擇一部著作,會通過 Ajax 實時獲得相關(guān)的名字,一個簡單的不涉及服務(wù)器的Ajax實例,需要的朋友可以參考下
    2014-05-05
  • js跨域調(diào)用WebService的簡單實例

    js跨域調(diào)用WebService的簡單實例

    下面小編就為大家?guī)硪黄猨s跨域調(diào)用WebService的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09

最新評論

宜城市| 岑巩县| 三河市| 科尔| 仁怀市| 察隅县| 马公市| 亚东县| 满洲里市| 宁武县| 吴川市| 罗甸县| 应城市| 望城县| 泰安市| 乐山市| 万山特区| 新邵县| 叶城县| 临清市| 卓资县| 邹城市| 枝江市| 遂平县| 甘谷县| 卢湾区| 宣化县| 靖江市| 海宁市| 南和县| 中超| 墨玉县| 昌邑市| 千阳县| 防城港市| 华坪县| 诏安县| 额济纳旗| 平武县| 石家庄市| 五寨县|