跨域是指a頁面想獲取b頁面資源,若是a、b頁面的協議、域名、端口、子域名不一樣,或是a頁面爲ip地址,b頁面爲域名地址,所進行的訪問行動都是跨域的,而瀏覽器爲了安全問題通常都限制了跨域訪問,也就是不容許跨域請求資源。javascript
跨域狀況以下:html
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 |
同一域名,不一樣二級域名(同上) | 是 |
目前來說沒有不依靠服務器端來跨域請求資源的技術前端
1.jsonp 須要目標服務器配合一個callback函數。html5
2.window.name+iframe 須要目標服務器響應window.name。java
3.window.location.hash+iframe 一樣須要目標服務器做處理。nginx
4.html5的 postMessage+ifrme 這個也是須要目標服務器或者說是目標頁面寫一個postMessage,主要側重於前端通信。ajax
5.CORS 須要服務器設置header :Access-Control-Allow-Origin。
shell
6.nginx反向代理 這個方法通常不多有人說起,可是他能夠不用目標服務器配合,不過須要你搭建一箇中轉nginx服務器,用於轉發請求。json
上面已經說到,禁止跨域問題實際上是瀏覽器的一種安全行爲,而如今的大多數解決方案都是用標籤能夠跨域訪問的這個漏洞或者是技巧去完成,但都少不了目標服務器作相應的改變,而我最近遇到了一個需求是,目標服務器不能給予我一個header,更不能夠改變代碼返回個script,因此前5種方案都被我否決掉。最後由於個人網站是我本身的主機,因此我決定搭建一個nginx並把相應代碼部署在它的下面,由頁面請求本域名的一個地址,轉由nginx代理處理後返回結果給頁面,並且這一切都是同步的。api
關於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¶=2;
咱們的ajax:
1
2
3
4
5
6
7
|
var
url =
'http://www.b.com/api/msg?method=1¶=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¶=2'
;
var
proxyurl =
'msg?method=1¶=2'
;
//假如實際地址是 www.c.com/proxy/html/api/msg?method=1¶=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¶=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