nginx解決跨域問題


 1.1 什么是跨域問題?

在前端領域中,跨域是指瀏覽器允許向服務器發送跨域請求,從而克服Ajax只能同源使用的限制。

一般根據錯誤來定位是否是跨域問題,報錯如下:

 

或者:

 

 

 

1.2 常見的跨域場景

 

URL

說明

是否允許通信

http://www.domain.com/a.js
http://www.domain.com/b.js
http://www.domain.com/lab/c.js

同一域名,不同文件或路徑

允許

http://www.domain.com:8000/a.js
http://www.domain.com/b.js

同一域名,不同端口

不允許

http://www.domain.com/a.js
https://www.domain.com/b.js

同一域名,不同協議

不允許

http://www.domain.com/a.js
http://192.168.4.12/b.js

域名和域名對應相同ip

不允許

http://www.domain.com/a.js
http://x.domain.com/b.js
http://domain.com/c.js

主域相同,子域不同

不允許

http://www.domain1.com/a.js
http://www.domain2.com/b.js

不同域名

不允許

 

 

1.3 如何解決跨域問題?

目前我了解的解決跨域的幾種方式:手寫過濾器,手寫攔截器,jsonnp,注解方式,配置nginx反向代理,共五種解決方式。

我們通常采用修改nginx配置文件來解決跨域問題

1.3.1 nginx代理跨域

nginx代理跨域,實質和CORS跨域原理一樣,通過配置文件設置請求響應頭Access-Control-Allow-Origin…等字段。

1)  nginx配置解決iconfont跨域

瀏覽器跨域訪問js、css、img等常規靜態資源被同源策略許可,但iconfont字體文件(eot|otf|ttf|woff|svg)例外,此時可在nginx的靜態資源服務器中加入以下配置。

 

2)  nginx反向代理接口跨域

跨域問題:同源策略僅是針對瀏覽器的安全策略。服務器端調用HTTP接口只是使用HTTP協議,不需要同源策略,也就不存在跨域問題。

實現思路:通過Nginx配置一個代理服務器域名與domain1相同,端口不同)做跳板機,反向代理訪問domain2接口,並且可以順便修改cookie中domain信息,方便當前域cookie寫入,實現跨域訪問。

nginx具體配置:

server {

      listen   8888;

      server_name test.demo.com;

      location / {

      proxy_pass http://120.147.88.27:8888;

      add_header Access-Control-Allow-Origin *;

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

      add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Authorization,Accept,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';

      #add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,Accept';

      add_header 'Access-Control-Allow-Headers' '*';

        }

}


詳細解釋:

add_header Access-Control-Allow-Methods *;

add_header Access-Control-Allow-Origin $http_origin;

 

add_header 'Access-Control-Allow-Origin' $http_origin;

add_header 'Access-Control-Allow-Credentials' 'true';

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

add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';

add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';

if ($request_method = 'OPTIONS') {

      add_header 'Access-Control-Max-Age' 1728000;

      add_header 'Content-Type' 'text/plain; charset=utf-8';

      add_header 'Content-Length' 0;

      return 204;

    }

 

1、Access-Control-Allow-Origin,這里使用變量 $http_origin取得當前來源域,大家說用“*”代表允許所有,我實際使用並不成功,原因未知;

2、Access-Control-Allow-Credentials,為 true 的時候指請求時可帶上Cookie,自己按情況配置吧;

3、Access-Control-Allow-Methods,OPTIONS一定要有的,另外一般也就GET和POST,如果你有其它的也可加進去;

4、Access-Control-Allow-Headers,這個要注意,里面一定要包含自定義的http頭字段(就是說前端請求接口時,如果在http頭里加了自定義的字段,這里配置一定要寫上相應的字段),從上面可看到我寫的比較長,我在網上搜索一些常用的寫進去了,里面有“web-token”和“app-token”,這個是我項目里前端請求時設置的,所以我在這里要寫上;

5、Access-Control-Expose-Headers,可不設置,看網上大致意思是默認只能獲返回頭的6個基本字段,要獲取其它額外的,先在這設置才能獲取它;

6、語句“ if ($request_method = 'OPTIONS') { ”,因為瀏覽器判斷是否允許跨域時會先往后端發一個 options 請求,然后根據返回的結果判斷是否允許跨域請求,所以這里單獨判斷這個請求,然后直接返回;

#   指定允許跨域的方法,*代表所有

add_header Access-Control-Allow-Methods *;

#   預檢命令的緩存,如果不緩存每次會發送兩次請求

add_header Access-Control-Max-Age 3600;

#   帶cookie請求需要加上這個字段,並設置為true

add_header Access-Control-Allow-Credentials true;

#   表示允許這個域跨域調用(客戶端發送請求的域名和端口)

#   $http_origin動態獲取請求客戶端請求的域   不用*的原因是帶cookie的請求不支持*號

add_header Access-Control-Allow-Origin $http_origin;

#   表示請求頭的字段 動態獲取

add_header Access-Control-Allow-Headers  $http_access_control_request_headers;

1.4 問題1:配置跨域不生效

1)使用nginx -V進行查看是否存在header模塊,如沒有則進行重新編譯安裝nginx

    --prefix=/app/nginx --with-http_ssl_module --with-stream --add-module=nginx-upload-module-2.2 --add-module=headers-more-nginx-module-master

2)下載這兩個模塊編譯即可

    headers-more-nginx-module-master.zip

    nginx-upload-module-2.2.zip

 

1.5 問題2: nginx會去掉帶有下划線的Header鍵值

原因:nginx對header name的字符做了限制,默認 underscores_in_headers 為off,表示如果    header name中包含下划線,則忽略掉,部署后就獲取不到。

解決:在header里不要用 “_” 下划線,可以用駝峰命名或者其他的符號(如減號-)代替。nginx默認忽略掉下划線可能有些原因。

在nginx里的 nginx.conf文件中配置http的部分添加 : underscores_in_headers on;(默認值是off)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM