最簡單實現跨域的方法:用 Nginx 反向代理

連接:http://blog.jobbole.com/101318/javascript

什麼是跨域html

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

所謂同源是指,域名,協議,端口相同。瀏覽器執行javascript腳本時,會檢查這個腳本屬於那個頁面,若是不是同源頁面,就不會被執行。python

同源策略的目的,是防止黑客作一些作奸犯科的勾當。好比說,若是一個銀行的一個應用容許用戶上傳網頁,若是沒有同源策略,黑客能夠編寫一個登錄表單提交到本身的服務器上,獲得一個看上去至關高大上的頁面。黑客把這個頁面經過郵件等發給用戶,用戶誤認爲這是某銀行的主網頁進行登錄,就會泄露本身的用戶數據。而由於瀏覽器的同源策略,黑客沒法收到表單數據。jquery

如今隨着RESTFUL的流行,不少應用提供http/https接口的API,經過xml/json格式對外提供服務,實現開放架構。如,微博、微信、天氣預報、openstack等網站和應用都提供restful接口。nginx

Web應用也在向單頁面方向發展。愈來愈多的web應用如今是這樣的架構:web

靜態單個web頁面ajax

ajax調用json

RESTFUL服務flask

咱們本能夠利用各個網站提供的API,作出不少精彩的Web應用。但瀏覽器執行javascript時的跨域限制,就成爲了這類開放架構的攔路虎。

本文提出了一種簡單有效的方式解決跨域問題。

經常使用的跨域方法

經常使用的跨域方法有這樣一些:

1,使用iFrame訪問另外一個域。 而後再從另外一個頁面讀取iFrame的內容。jquery等有一些封裝。聽說Firefox等可能不支持讀取另外一個iFrame的內容。

2,jsonp。須要服務器支持。使用script src動態獲得一段java代碼。是回調頁面上的js函數,參數是一個json對象。jquery也有封裝。

3,設置http頭,Access-Control-Allow-Origin:*但聽說IE有一些版本不識別這個http頭。

4,服務器代理。如,服務器寫一個url的處理action。其參數是一個url。這個服務器會用參數拼湊一個url,用httpclient庫去執行url,而後把讀取的內容再輸出到http客戶端。

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,那怎麼處理呢?

咱們這樣編寫nginx的配置文件:

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,以此類推。

總結

本文介紹了利用nginx的反向代理的功能,實現跨域訪問任意應用和網站的方法。

nginx是一個高性能的web服務器,經常使用做反向代理服務器。nginx做爲反向代理服務器,就是把http請求轉發到另外一個或者一些服務器上。

經過把本地一個url前綴映射到要跨域訪問的web服務器上,就能夠實現跨域訪問。

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

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

這樣,爲了解決跨域問題,只須要動一下nginx配置文件便可。簡單、強大、高效!

相關文章
相關標籤/搜索