Nginx解決CORS跨域解決方案

首先通讀下 MDN 關於 CORS 的 定義,瞭解跨域的含義及簡單請求和複雜請求等的定義。文中的內容不贅述,現在說解決方案。

通過定義我們可以,簡單請求與複雜請求的差別是複雜請求會自動發出一個 OPTIONS 的預檢請求,當請求得到確認後,纔開始真正發送請求。

綜上,我們要解決兩個問題:

  1. OPTIONS 請求的正確響應
  2. 跨域請求正確響應

1、OPTIONS 請求的正確響應

解決的方式有多種,既可以在Web Server解決,也可以在源碼層解決。因爲問題比較普遍,故我們選擇在Web Server解決,下面我們以 Nginx 爲例,說明解決方案。

假設訪問的地址爲 /example , Nginx 配置如下:

location /example {
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080/;
  }

爲了解決跨域問題,添加如下內容:

location /example {
+   if ($request_method = 'OPTIONS') {
+       add_header Access-Control-Allow-Origin *;
+       add_header Access-Control-Max-Age 1728000;
+       add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
+       add_header Access-Control-Allow-Headers  'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
+       add_header Content-Type' 'text/plain; charset=utf-8';
+       add_header Content-Length 0 ;
+       return 204;
+    }

    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080/;
   }

解釋:

if ($request_method = 'OPTIONS') {...} 當請求方法爲 OPTIONS 時:
1、添加允許源 Access-Control-Allow-Origin 爲 * (可根據業務需要更改)
2、添加緩存時長 Access-Control-Max-Age,當下次請求時,無需再發送 OPTIONS 請求
3、添加允許的方法,允許的首部
4、添加一個內容長度爲0,類型爲 text/plain; charset=utf-8 , 返回狀態碼爲 204 的首部
至此,完成 OPTIONS 請求的正確響應。

2、跨域請求正確響應

添加如下內容:

location /example {
   if ($request_method = 'OPTIONS') {
       add_header Access-Control-Allow-Origin *;
       add_header Access-Control-Max-Age 1728000;
       add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
       add_header Access-Control-Allow-Headers  'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
       add_header Content-Type' 'text/plain; charset=utf-8';
       add_header Content-Length 0 ;
       return 204;
    }

+   if ($http_origin ~* (https?://(.+\.)?(example\.com$))) {
+     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-Expose-Headers Content-Length,Content-Range;
+   }

    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080/;
   }

解釋:

if ($http_origin ~* (https?://(.+\.)?(example\.com$))) {...}, 當 origin 爲合法域名(可根據業務調整或去除合法域名驗證)時:
1、添加允許源Access-Control-Allow-Origin$http_origin (可根據業務需要更改)
2、添加允許認證Access-Control-Allow-Credentialstrue ,允許接收客戶端 Cookie(可根據業務需要更改。 但要注意,當設置爲true時,Access-Control-Allow-Origin 不允許設置爲 *)
3、添加允許的方法,暴露的首部

至此,完成跨域請求正確響應。

以上,是對跨域請求在Web Server的解決方案,主要是通過響應 OPTIONS 方法和添加允許源來解決。

當然,如果本地開發中,可以在利用 webpack-dev-serverproxy 選項來快速解決跨域問題:
示例如下:

// webpack.congf.js

module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: {'^/api' : ''}
      }
    }
  }
}

當訪問地址如 /api/foo?q=bar 時,則通過代理訪問的實際地址是: http://localhost:3000/foo?q=bar

CORS跨域請求並不魔幻,理解 CORS 的含義,根據規則去找方法就迎刃而解了。希望能幫助到大家。

轉自

https://my.oschina.net/liuyuantao/blog/1931256

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章