跨域問題出現原因和解決方案


一、出現原因

跨域是指a頁面想獲取b頁面資源,如果a、b頁面的協議、域名、端口、子域名不同,或是a頁面為ip地址,b頁面為域名地址,所進行的訪問行動都是跨域的,而瀏覽器為了安全問題一般都限制了跨域訪問,也就是不允許跨域請求資源。

例如:

URL 說明 是否跨域
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同域名下不同文件
http://www.cnblogs.com/a.js 
http://www.a.com/b.js
不同域名
http://www.a.com:8000/a.js 
http://www.a.com/b.js
同域名下不同端口
http://www.a.com/a.js 
https://www.a.com/b.js
同域名 不同協議
http://www.a.com/a.js 
http://70.32.92.74/b.js
域名和域名對應ip
http://www.a.com/a.js 
http://script.a.com/b.js
主域名相同 子域名不同
http://www.a.com/a.js 
http://a.com/b.js
同一域名,不同二級域名(同上)

二、解決方案

【策略一】:Jsonp:需要目標服務器配合一個callback函數

JSONP(JSON with Padding)是一個非官方的協議,它允許在服務器端集成Script tags返回至客戶端,通過javascript callback的形式實現跨域訪問(這僅僅是JSONP簡單的實現形式)。
Json+padding(內填充),顧名思義,就是把JSON填充到一個盒子里,它的基本思想是,網頁通過添加一個<script>元素,向服務器請求JSON數據,這種做法不受同源政策限制;服務器收到請求后,將數據放在一個指定名字的回調函數里傳回來。
首先,網頁動態插入<script>元素,由它向跨源網址發出請求。

JSONP的產生:

1.AJAX直接請求普通文件存在跨域無權限訪問的問題,不管是靜態頁面也好.
2.不過我們在調用js文件的時候又不受跨域影響,比如引入jquery框架的,或者是調用相片的時候
3.凡是擁有scr這個屬性的標簽都可以跨域例如<script><img><iframe>
4.如果想通過純web端跨域訪問數據只有一種可能,那就是把遠程服務器上的數據裝進js格式的文件里.
5.而json又是一個輕量級的數據格式,還被js原生支持
6.為了便於客戶端使用數據,逐漸形成了一種非正式傳輸協議,人們把它稱作JSONP,該協議的一個要點就是允許用戶傳遞一個callback 參數給服務端

Js 客戶端 方案一:

<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />  
<script type="text/javascript">  
    function jsonpCallback(result) {  
        //alert(result);  
        for(var i in result) {  
            alert(i+":"+result[i]);//循環輸出a:1,b:2,etc.  
        }  
    }  
    var JSONP=document.createElement("script");  
    JSONP.type="text/javascript";  
    JSONP.src="http://crossdomain.com/services.php?callback=jsonpCallback";  
    document.getElementsByTagName("head")[0].appendChild(JSONP);  
</script> 

Js 客戶端 方案二:

<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />  
<script type="text/javascript">  
    function jsonpCallback(result) {  
        alert(result.a);  
        alert(result.b);  
        alert(result.c);  
        for(var i in result) {  
            alert(i+":"+result[i]);//循環輸出a:1,b:2,etc.  
        }  
    }  
</script>  
<script type="text/javascript" src="http://crossdomain.com/services.php?callback=jsonpCallback"></script>

Jquery 客戶端 方案一:

<script type="text/javascript" src="jquery.js"></script>  
<script type="text/javascript">  
    $.getJSON("http://crossdomain.com/services.php?callback=?",  
    function(result) {  
        for(var i in result) {  
            alert(i+":"+result[i]);//循環輸出a:1,b:2,etc.  
        }  
    });  
</script> 

Jquery 客戶端 方案二:

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
    $.ajax({
        url:"http://crossdomain.com/services.php",
        type:'get',//注意:跨域請求是只能是get請求不能使用post請求
        dataType:'jsonp',
        data:'',
        jsonp:'callback',//傳遞給請求處理程序或頁面的,用以獲得jsonp回調函數名的參數名(默認為:callback)
        jsonpCallback:"success",//自定義的jsonp回調函數名稱,默認為jQuery自動生成的隨機函數名
        success:function(result) {
            console.log(result);
        },
        timeout:3000
    });
</script>

Jquery 客戶端 方案三:

<script type="text/javascript" src="jquery.js"></script>  
<script type="text/javascript">  
    $.get('http://crossdomain.com/services.php?callback=?', {name: encodeURIComponent('tester')}, function (json) { for(var i in json) alert(i+":"+json[i]); }, 'jsonp');  
</script>

 PHP 服務端:

//服務端返回JSON數據
$arr=array('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
$result=json_encode($arr);
//動態執行回調函數
$callback=$_GET['callback'];
echo $callback."($result)";

【策略二】基於iframe實現的跨子域:通過修改document.domain來跨子域

將子域和主域的document.domain設為同一個主域.前提條件:這兩個域名必須屬於同一個基礎域名!而且所用的協議,端口都要一致,否則無法利用document.domain進行跨域
主域相同的使用document.domain

【策略三】PHP設置header頭來實現跨域

 

//Access-Control-Allow-Origin:指定允許其他域名訪問。該字段是必須的。它的值要么是請求時Origin字段的值,要么是一個*,表示接受任意域名的請求。
header('Access-Control-Allow-Origin:*');
//Access-Control-Allow-Methods:響應類型
header('Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS');
//Access-Control-Allow-Headers:響應頭設置
header('Access-Control-Allow-Headers:X-Requested-With,Content-Type');
//Access-Control-Expose-Headers:該字段可選。CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定。
header('Access-Control-Expose-Headers:Authorization');

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM