1. 程式人生 > 其它 >Nginx解決跨域請求,通俗解釋

Nginx解決跨域請求,通俗解釋

摘自:https://segmentfault.com/a/1190000022415375

一、Nginx

關於Nginx的用途,聽到最多的兩個詞,就是:

  • 埠轉發
  • 負載均衡

負載均衡不屬於現階段要學習的內容,重點來看一看埠轉發,本文用它來解決跨域請求的問題。

二、CROS 跨域資源共享

我們需要知道,同源的三要素:協議、域名、埠。

如果比較兩個地址,只要三者中只要有任何一個不同,就算跨域。

// 協議:http
// 域名:localhost
// 埠:8011

http://localhost:8011

出於安全原因,瀏覽器限制從指令碼(比如JavaScript)內發起的跨源HTTP請求。

如果瀏覽器檢測到跨域,它會嘗試發起一次請求,然後檢視返回的內容中,是否一個有允許跨域請求的標記(CORS響應頭),如果有正確的標記,那麼就不攔截;如果沒有標記,瀏覽器就會阻止這個請求。並報錯。

三、專案中為何產生跨域

在前後臺分離的專案中,前臺和後臺分別執行在不同的埠上。

所以前臺向後臺發起請求時,會因為跨域,而被瀏覽器攔截下來。

瀏覽器錯誤資訊:

這時解決方案有兩個:

  • 開放跨域請求
  • 使跨域變成同源

第一種方法,顯然不安全,開放跨域意味著,瀏覽器不再進行攔截。如果前臺程式碼被篡改,把後臺的地址指向黑客的伺服器,那麼會對使用者造成損失。

第二種方法,想辦法變成同一個域,這就輪到Nginx出場了!

四、使用Nginx轉發

首先要明白,是誰把前臺向後臺的請求攔截下來的?不是後臺,而是瀏覽器。

如果要避免跨域,只要讓瀏覽器認為“我正在向同一個域發起請求”,就可以了。

假設前臺使用4200埠,後臺使用8080埠,那麼,再加入一個8011埠,作為使用者訪問時連線的埠。

在前臺的程式碼中,會有攔截器,如果發現某個請求是指向後臺的,就會在Url中加入一個特殊的標識(比如加一個/api/作為字首)

// header中帶有do_not_intercept,且值為true,則不新增url字首
if (('true' !== req.headers.get(YunzhiInterceptor.DONT_INTERCEPT_HEADER_KEY))
  && !url.startsWith('https://') && !url.startsWith('http://')) {
  url = '/api/' + url;
}

現在,無論是指向前臺還是後臺的請求,都會發送到8011埠,只不過,指向後臺的請求會有一個/api/字首。

接下來使用Nginx監聽8011埠,當接收到請求時,根據是否有字首,來判斷此請求交給前臺或後臺處理。

過程如圖:

上圖就是轉發的原理。

五、總結

使用Nginx埠轉發,本質上就是:讓瀏覽器認為前臺和後臺是同一個域,就不會產生跨域請求。

開發者事先約定好,根據不同的請求地址,來訪問不同的伺服器。

Nginx接收到資料之後,根據地址,轉發給相應的伺服器來處理。

如果需要另外安排其他的服務,來實現檔案上傳功能的話,只需要把URL處理一下,加上不同的字首即可。