前端經過Nginx反向代理解決跨域問題

解決方式主要有以下三種方式:

JSONP
CORS
WebSocket
但是這幾種方式都是基於服務器配置的,即對於本身的網站是能夠經過這幾種方式解決的,但是如今遇到另外一個需求(前面提到過,寫扇貝插件,咱們不能更改扇貝的服務器配置,也不能發短信叫他們給我配置一下)。

本文探討了前端如何經過Nginx反向代理的方式解決跨域問題。

跨域
再次重申: 跨域是瀏覽器行爲,不是服務器行爲。

實際上,請求已經到達服務器了,只不過在回來的時候被瀏覽器限制了。就像Python他能夠進行抓取數據同樣,不通過瀏覽器而發起請求是能夠獲得數據,想到經過Nginx的反向代理來解決跨域問題。

代理
所謂代理就是在咱們和真實的服務器之間有一臺代理服務器,咱們全部的請求都是經過它來進行轉接的。

正向代理
正向代理就是咱們訪問不了Google,可是我在國外有一臺vps,它能夠訪問Google,我訪問它,叫它訪問Google後,把數據傳給我。

正向代理隱藏了真實的客戶端。

反向代理
你們都有過這樣的經歷,撥打10086客服電話,可能一個地區的10086客服有幾個或者幾十個,你永遠都不須要關心在電話那頭的是哪個,叫什麼,男的,仍是女的,漂亮的仍是帥氣的,你都不關心,你關心的是你的問題能不能獲得專業的解答,你只須要撥通了10086的總機號碼,電話那頭總會有人會回答你,只是有時慢有時快而已。那麼這裏的10086總機號碼就是咱們說的反向代理。客戶不知道真正提供服務人的是誰。

反向代理隱藏了真實的服務端,當咱們請求 www.baidu.com 的時候,就像撥打10086同樣,背後可能有成千上萬臺服務器爲咱們服務,但具體是哪一臺,你不知道,也不須要知道,你只須要知道反向代理服務器是誰就行了,www.baidu.com 就是咱們的反向代理服務器,反向代理服務器會幫咱們把請求轉發到真實的服務器那裏去。Nginx就是性能很是好的反向代理服務器,用來作負載均衡。



反向代理

反向代理隱藏了真實的服務器。

Nginx 就是一個很好的反向代理服務器,固然apache也能夠實現此功能。

windows下Apache配置參考這篇文章: Windows Apache服務器配置

Nginx
Nginx(發音同engine x)是一個 Web服務器,也能夠用做反向代理,負載平衡器和 HTTP緩存。該軟件由 Igor Sysoev 建立,並於2004年首次公開發布。同名公司成立於2011年,以提供支持。

我在Windows下實現Nginx負載均衡提到過Windows下Nginx命令使用。

Nginx 反向代理模塊 proxy_pass
proxy_pass 後面跟着一個 URL,用來將請求反向代理到 URL 參數指定的服務器上。例如咱們上面例子中的 proxy_pass https://api.shanbay.com,則將匹配的請求反向代理到 https://api.shanbay.com。

經過在配置文件中增長proxy_pass 你的服務器ip,例如這裏的扇貝服務器地址,就能夠完成反向代理。

html

[JavaScript]
純文本查看
複製代碼
?
01
02
03
04
05
06
07
08
09
10
server {
listen 80;
server_name localhost;
## 用戶訪問 localhost,則反向代理到https://api.shanbay.com
location / {
root html;
index index.html index.htm;
proxy_pass https: //api.shanbay.com;
}
}


配置html以文件方式打開
通常的狀況下,咱們的HTML文件時放置在Nginx服務器上面的,即經過輸入 http://localhost/index.html ,可是在前端進行調試的時候,咱們多是經過 使用 file:///E:/nginx/html/index.html 來打開HTML。服務器打開不是特別方便。

而咱們之因此要部署在服務器上,是想要使用瀏覽器自帶的CORS頭來解決跨域問題,若是不想把HTML放置在Nginx中,而想經過本地打開的方式來調試HTML,能夠經過本身添加Access-Control-Allow-Origin等http頭,可是咱們的AJAX請求必定要加上http://127.0.0.1/request,而不能直接是 /request,因而將nginx.conf做以下配置:

前端

[JavaScript]
純文本查看
複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
location / {
root html;
index index.html index.htm;
# 配置html以文件方式打開
if ($request_method = 'POST' ) {
add_header 'Access-Control-Allow-Origin' *;
add_header 'Access-Control-Allow-Credentials' 'true' ;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' ;
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' ;
}
if ($request_method = 'GET' ) {
add_header 'Access-Control-Allow-Origin' *;
add_header 'Access-Control-Allow-Credentials' 'true' ;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' ;
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' ;
}


# 代理到8080端口
proxy_pass http://127.0.0.1:8080;

}
處理DELETE和PUT跨域請求
而如今個人後臺是restful風格的接口,採用了delete和put方法,而上面的配置就無能爲力了。

能夠經過增長對非簡單請求的判斷來解決DELETE和PUT跨域請求。

非簡單請求是那種對服務器有特殊要求的請求,好比請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json。

非簡單請求的CORS請求,會在正式通訊以前,增長一次HTTP查詢請求,稱爲"預檢"請求(preflight)。

服務器收到"預檢"請求之後,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段之後,確認容許跨源請求,就能夠作出迴應。

所以,爲了使Nginx能夠處理delete等非簡單請求,Nginx須要做出相應的改變,更改配置以下

nginx

[JavaScript]
純文本查看
複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
location / {
# 完成瀏覽器的"預檢"請求
if ($request_method = 'OPTIONS' ) {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true ;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' ;
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' ;
return 204;
}
# 配置html在本地打開
if ($request_method = 'POST' ) {
add_header 'Access-Control-Allow-Origin' *;
add_header 'Access-Control-Allow-Credentials' 'true' ;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' ;
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' ;
}
if ($request_method = 'GET' ) {
add_header 'Access-Control-Allow-Origin' *;
add_header 'Access-Control-Allow-Credentials' 'true' ;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' ;
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' ;
}
root html;
index index.html index.htm;
# 配置html在Nginx中打開
location ~* \.(html|htm)$ {
}


# 代理到8080端口
proxy_pass http://127.0.0.1:8080;

}
咱們還必須把咱們的html代碼放在Nginx中html文件夾內,即便用Nginx當作咱們的前端服務器。

URL重寫
有時候咱們僅僅只想將/api下的url反向代理到後端,能夠經過在nginx.conf中配置url重寫規則以下:

apache

[JavaScript]
純文本查看
複製代碼
?
1
2
3
4
5
6
7
8
location / {
root html;
index index.html index.htm;
location ^~ /api {
rewrite ^/api/(.*)$ /$1 break ;
proxy_pass https: //api.shanbay.com/;
}
}


這樣的話,咱們只用處理/api下的url。

在配置文件中咱們經過rewrite將URL重寫爲真正要請求的URL,經過proxy_pass代理到真實的服務器IP或者域名。

Cookie
若是Cookie的域名部分與當前頁面的域名不匹配就沒法寫入。因此若是請求 www.a.com ,服務器 proxy_pass 到 www.b.com 域名,而後 www.b.com 輸出 domian=b.com 的 Cookie,前端的頁面依然停留在 www.a.com 上,因而瀏覽器就沒法將 Cookie 寫入。

可在nginx反向代理中設置:

json

[JavaScript]
純文本查看
複製代碼
?
1
2
3
4
5
location / {
# 頁面地址是a.com,可是要用b.com的cookie
proxy_cookie_domain b.com a.com; #注意別寫錯位置了 proxy_cookie_path / /;
proxy_pass http: //b.com;
}


總結
Nginx解決跨域問題經過Nginx反向代理將對真實服務器的請求轉移到本機服務器來避免瀏覽器的"同源策略限制"。本文轉自https://blog.csdn.net/weixin_39923425/article/details/81217337
windows

相關文章
相關標籤/搜索