1. 程式人生 > >前端開發介面聯調--用nginx的反向代理機制解決前端跨域問題

前端開發介面聯調--用nginx的反向代理機制解決前端跨域問題

轉載自:http://www.cnblogs.com/fengnovo/p/6230866.html

      http://www.cnblogs.com/gabrielchen/p/5066120.html

前端開發用nginx代理伺服器解決伺服器跨域問題及跨域訪問https訪問(mac系統下)

前端開發經常遇到一些伺服器由於跨域造成訪問不了的情況。以前BS模式,前後端都是一個人開發,跨域問題造成的開發阻礙不是很明顯,但是現在前端框架欣欣向榮,很多時候變成了CS模式的開發,但瀏覽器天生的跨域限制,造成了開發,特別是對單獨的前端開發人員(不太懂後臺開發的人)造成一定開發障礙。還好有nodejs及其一系列前端自動化工具很好的解決了開發時的問題。但今天我要說的用nginx代理來解決這個問題。我覺得很簡單!
以下都是基於mac系統的操作!
先看沒有代理時,隨便訪問網上一個介面, http://web.juhe.cn:8080/finance/exchange/rmbquot

1

2

3

$.get('http://web.juhe.cn:8080/finance/exchange/rmbquot',function(data){

$('#app').html(data);

})

會發現瀏覽器下面,


1.安裝nginx伺服器,可以看我的這篇部落格http://www.cnblogs.com/fengnovo/p/6230013.html

2.修改下 /usr/local/etc/nginx/nginx.conf 檔案,將

1

server {}  包起來那段修改為以下的

1

2

3

4

5

6

7

8

9

add_header Access-Control-Allow-Origin *;

add_header Access-Control-Allow-Headers X-Requested-With;

add_header Access-Control-Allow-Methods GET,POST,OPTIONS;

server {

listen 8000;

location /api {

proxy_pass http:

//web.juhe.cn:8080/finance/exchange/rmbquot; <br>     } <br>}

上面三句是設定伺服器端允許請求的客戶端跨域,
下面幾句話是將監聽本機(localhost)8000埠,將8000埠/api請求轉發到 http://web.juhe.cn:8080/finance/exchange/rmbquot

3.然後啟動nginx伺服器

4.再修改自己的程式碼,將http://web.juhe.cn:8080/finance/exchange/rmbquot改為指向自己nginx伺服器http://localhost:8000/api

1

2

$.get('http://localhost:8000/api',function(data){

$('#app').html(data);<br>})

5.這時再訪問,就可以將伺服器返回的資料打印出來不會再出現No 'Access-Control-Allow-Origin' header is present報錯


6.對於https的請求也是一樣代理,將 proxy_pass http://web.juhe.cn:8080/finance/exchange/rmbquot; 改為 proxy_pass https://xxx.com; 

用nginx的反向代理機制解決前端跨域問題

1.什麼是跨域以及產生原因

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

  跨域情況如下:

url 說明 是否跨域
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名
http://www.a.com/lab/a.js
http://www.a.com/script/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
主域相同,子域不同 是(cookie不可訪問)
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二級域名(同上)

2.跨域的常見解決方法

目前來講沒有不依靠伺服器端來跨域請求資源的技術

  1.jsonp 需要目標伺服器配合一個callback函式。

  2.window.name+iframe 需要目標伺服器響應window.name。

  3.window.location.hash+iframe 同樣需要目標伺服器作處理。

  4.html5的 postMessage+ifrme 這個也是需要目標伺服器或者說是目標頁面寫一個postMessage,主要側重於前端通訊。

  5.CORS  需要伺服器設定header :Access-Control-Allow-Origin。

  6.nginx反向代理 這個方法一般很少有人提及,但是他可以不用目標伺服器配合,不過需要你搭建一箇中轉nginx伺服器,用於轉發請求。

3.nginx反向代理解決跨域

  上面已經說到,禁止跨域問題其實是瀏覽器的一種安全行為,而現在的大多數解決方案都是用標籤可以跨域訪問的這個漏洞或者是技巧去完成,但都少不了目標伺服器做相應的改變,而我最近遇到了一個需求是,目標伺服器不能給予我一個header,更不可以改變程式碼返回個script,所以前5種方案都被我否決掉。最後因為我的網站是我自己的主機,所以我決定搭建一個nginx並把相應程式碼部署在它的下面,由頁面請求本域名的一個地址,轉由nginx代理處理後返回結果給頁面,而且這一切都是同步的。

  關於nginx的一些請看我的另一篇部落格,下面直接講解如何配置一個反向代理。

  首先找到nginx.conf或者nginx.conf.default 或者是default裡面的這部份   

          

   其中server代表啟動的一個服務,location 是一個定位規則。

1

2

3

4

5

6

7

location /{   #所有以/開頭的地址,實際上是所有請求

root  html     #去請求../html資料夾裡的檔案,其中..的路徑在nginx裡面有定義,安裝的時候會有預設路徑,詳見另一篇部落格

index  index.html index.htm  #首頁響應地址

  從上面可以看出location是nginx用來路由的入口,所以我們接下來要在location裡面完成我們的反向代理。

  假如我們我們是www.a.com/html/msg.html 想請求www.b.com/api/?method=1&para=2;

  我們的ajax:

1

2

3

4

5

6

7

var url = 'http://www.b.com/api/msg?method=1&para=2'

<br>$.ajax({

type: "GET",

url:url,

success: function(res){..},

....

})

  上面的請求必然會遇到跨域問題,這時我們需要修改一下我們的請求url,讓請求發在nginx的一個url下。

1

2

3

4

5

6

7

8

9

var url = 'http://www.b.com/api/msg?method=1&para=2'

var proxyurl = 'msg?method=1&para=2'

//假如實際地址是 www.c.com/proxy/html/api/msg?method=1&para=2; www.c.com是nginx主機地址

$.ajax({

type: "GET",

url:proxyurl,

success: function(res){..},

....

})  

  再在剛才的路徑中匹配到這個請求,我們在location下面再新增一個location。

1

2

3

4

location ^~/proxy/html/{

rewrite ^/proxy/html/(.*)$ /$1 break;

proxy_pass http://www.b.com/;

}

以下做一個解釋:

1.'^~ /proxy/html/ '

  就像上面說的一樣是一個匹配規則,用於攔截請求,匹配任何以 /proxy/html/開頭的地址,匹配符合以後,停止往下搜尋正則。

2.rewrite ^/proxy/html/(.*)$ /$1 break;

  代表重寫攔截進來的請求,並且只能對域名後邊的除去傳遞的引數外的字串起作用,例如www.c.com/proxy/html/api/msg?method=1&para=2重寫。只對/proxy/html/api/msg重寫。

  rewrite後面的引數是一個簡單的正則 ^/proxy/html/(.*)$ ,$1代表正則中的第一個(),$2代表第二個()的值,以此類推。

  break代表匹配一個之後停止匹配。

3.proxy_pass

  既是把請求代理到其他主機,其中 http://www.b.com/ 寫法和 http://www.b.com寫法的區別如下:

不帶/

1

2

3

4

location /html/

{

  proxy_pass http://b.com:8300; 

}

帶/

1

2

3

4

location /html/ 

proxy_pass http://b.com:8300/; 

}

上面兩種配置,區別只在於proxy_pass轉發的路徑後是否帶 “/”。

  針對情況1,如果訪問url = http://server/html/test.jsp,則被nginx代理後,請求路徑會便問http://proxy_pass/html/test.jsp,將test/ 作為根路徑,請求test/路徑下的資源。

  針對情況2,如果訪問url = http://server/html/test.jsp,則被nginx代理後,請求路徑會變為 http://proxy_pass/test.jsp,直接訪問server的根資源。

修改配置後重啟nginx代理就成功了。

參考:http://seanlook.com/2015/05/17/nginx-location-rewrite/

         http://www.jbxue.com/article/2187.html