ajax跨域問題完美解決

背景:今天被問到,不會答,好久沒有用到,瞬間感覺自己好菜,有點不爽,之前配過nginx的,然後面試官還叫我找出這個文章,日記存在企鵝空間的,半天沒找出來那篇文章,然後被面試過鄙視了,回來趕緊搜索一下。
下面是查找到的答案,然後自己測試通過,下次再問我,我就搬這邊文章出來給他看。
什麼是跨域?

跨域,指的是瀏覽器不能執行其他網站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器施加的安全限制。

所謂同源是指,域名,協議,端口均相同,不明白沒關係,舉個栗子:

http://www.123.com/index.html 調用 http://www.123.com/server.php (非跨域)

http://www.123.com/index.html 調用 http://www.456.com/server.php (主域名不同:123/456,跨域)

http://abc.123.com/index.html 調用 http://def.123.com/server.php (子域名不同:abc/def,跨域)

http://www.123.com:8080/index.html 調用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)

http://www.123.com/index.html 調用 https://www.123.com/server.php (協議不同:http/https,跨域)

請注意:localhost和127.0.0.1雖然都指向本機,但也屬於跨域。
瀏覽器執行javascript腳本時,會檢查這個腳本屬於哪個頁面,如果不是同源頁面,就不會被執行。
跨域有:
1.不同域名肯定是跨域了
2.admin.xx.com/www.xx.com同域名,子域名不同跨域,
3.同域名不同端口跨域
**

解決辦法:1、加header頭接收所有請求:

**
首先在本地配置兩個域名:
host文件加上這兩行
127.0.0.1 www.dd.com
127.0.0.1 www.abc.com
nginx server 1

server{
        listen       80;
        server_name  www.abc.com;
        root   "D:/phpStudy/WWW/abc";
        location / {
            index  index.php index.htm /public/index.html;
           autoindex  off;
        }
        location ~ \.php(.*)$  {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO  $fastcgi_path_info;
            fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
            include        fastcgi_params;
        }
    }

nginx server 2

server {
        listen       80;
        server_name  www.dd.com;
        root   "D:/phpStudy/WWW/ddpay";
        location / {
            index  index.php index.htm /public/index.html;
           autoindex  off;
        }
        location ~ \.php(.*)$  {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO  $fastcgi_path_info;
            fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
            include        fastcgi_params;
        }
    }

ajax跨域請求的服務端代碼:
就是接收一段請求返回一段json字符串的意思,這個大家都懂的

 public function  hey(){
        header('Access-Control-Allow-Origin:*');//允許所有來源訪問
        header('Access-Control-Allow-Method:POST,GET');//允許訪問的方式
        $data = I('postData');
        $response['msg'] = "i get it . are you ok? ".$data;
        echo json_encode($response);
        exit();//這裏一定要加上exit,不然你會懷疑人生的!
    }

//ajax跨域abc.com發起ajax請求代碼:

    $("#test_ajax").click(function(){
            var postData = "halou ,guy!";
            $.post('http://www.dd.com/index.php/Home/mall/hey',{'postData':postData},function(data){
                alert(data.msg);
            });

        });

服務端響應完畢如果不加exit()退出,會返回json字符串和一堆沒用的東西,在客戶端那邊看着就一臉懵逼了,一定要加上去,不然某些框架還會繼續有其他操作的

2. jsonp解決,但只支持get請求,不支持Post請求

網上搜索了2小時………. IE10-以下不兼容,算!!!!

3.NGINX代理方式處理請求

nginx反向代理實現跨域
上面提到的這些跨域方法,都有一些問題。有的不能支持所有瀏覽器,有的需要修改javascript代碼,有的需要重寫服務器端代碼。有的在session等場景下會有問題。

其實,用nginx反向代理實現跨域,是最簡單的跨域方式。只需要修改nginx的配置即可解決跨域問題,支持所有瀏覽器,支持session,不需要修改任何代碼,並且不會影響服務器性能。
我們只需要配置nginx,在一個服務器上配置多個前綴來轉發http/https請求到多個真實的服務器即可。這樣,這個服務器上所有url都是相同的域名、協議和端口。因此,對於瀏覽器來說,這些url都是同源的,沒有跨域限制。而實際上,這些url實際上由物理服務器提供服務。這些服務器內的javascript可以跨域調用所有這些服務器上的url。

下面,給出一個nginx支持跨域的例子,進行具體說明。
如,我們有兩個pythonflask開發的項目:testFlask1和testFlask2。
testFlask2項目上的javascript腳本要通過ajax方式調用testFlask1的一個url,獲取一些數據。
正常情況下部署,就會有跨域問題,瀏覽器拒絕執行如下這樣的調用。

$("button").click(function(){
   $.get("127.0.0.1:8081/partners/json",
   function(result){
      $("div").html(result);
   });
});

下面把testFlask2項目的javascrip文件修改一下。這樣訪問同源的url,就不會有跨域問題。

$("button").click(function(){
    $.get("partners/json",
    function(result){
     $("div").html(result);
    });
});

但是,我們testFlask2項目實際上沒有partners/json這樣的url,那怎麼處理呢?

server{
listen8000;
location/ {
includeuwsgi_params;

uwsgi_passunix:/tmp/testFlask2.sock;
}
location/partners {
rewrite^.+partners/?(.*)$ /$1 break;
includeuwsgi_params;

uwsgi_passunix:/tmp/testFlask1.sock;
}

}

我們把testFlask2項目部署在8080端口的根目錄下。把提供web服務的testFlask1項目部署在/partners目錄下。

但我們的testFlask1項目並不能處理/partners/json這樣的url請求。那怎麼辦呢?

通過 rewrite^.+partners/?(.)/ 1 break; 這一條命令,nginx可以把收到的/partners/請求全部轉爲/*請求後再轉發給背後的真實web服務器。

這樣,RESTFUL的ajax客戶端程序,只需要給出特定前綴的url就可以調用任意服務器提供的RESTFUL接口了。

甚至,通過nginx的反向代理,我們還能調用其他公司開發的網站提供的RESTFUL接口。

如,

location/sohu {
rewrite^.+sohu/?(.*)$ /$1 break;
includeuwsgi_params;

proxy_passhttp://www.sohu.com/;
}

我們就把sohu網站整個搬到我們的8080:/sohu/目錄下了,我們的javascript就可以盡情調用其RESTFUL服務了。

順便說一下,rewrite^.+sohu/?(.*)/ 1 break; 這句命令中,1(.)() 1,第二對()內的參數就是$2,以此類推。
通過把本地一個url前綴映射到要跨域訪問的web服務器上,就可以實現跨域訪問。

對於瀏覽器來說,訪問的就是同源服務器上的一個url。而nginx通過檢測url前綴,把http請求轉發到後面真實的物理服務器。並通過rewrite命令把前綴再去掉。這樣真實的服務器就可以正確處理請求,並且並不知道這個請求是來自代理服務器的。

簡單說,nginx服務器欺騙了瀏覽器,讓它認爲這是同源調用,從而解決了瀏覽器的跨域問題。又通過重寫url,欺騙了真實的服務器,讓它以爲這個http請求是直接來自與用戶瀏覽器的。

我們這樣編寫nginx的配置文件:
原文地址:http://blog.csdn.net/lambert310/article/details/51683775
其他參考地址好多好多好多…..

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