跨域解決方案(CORS)

跨域解決方案(CORS)

1. 什麼是跨域?

​ 跨域問題是出於瀏覽器的【同源策略】限制。同源策略(Sameoriginpolicy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。同源策略會阻止一個域的javascript腳本和另外一個域的內容進行交互。

​ 所謂同源(即指在同一個域)就是兩個頁面具有相同的協議(protocol),主機(host)和端口號(port)

​ 由於我們現在是採用的前後端分離的微服務架構,前端和後端必定存在跨域問題。解決跨域問題可以採用CORS。

2. CORS簡介

  CORS 是一個 W3C 標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。

​ CORS需要瀏覽器和服務器同時支持。但是目前基本上瀏覽器都支持,所以我們只要保證服務器端服務器實現了 CORS 接口,就可以跨源通信。

​ 瀏覽器將CORS請求分成兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。

3. 具體解決方式

解決跨域問題,就是在服務器端給響應添加頭信息

Name Required Comments
Access-Control-Allow-Origin 必填 允許請求的域
Access-Control-Allow-Methods 必填 允許請求的方法
Access-Control-Allow-Headers 可選 預檢請求後,告知發送請求需要有的頭部
Access-Control-Allow-Credentials 可選 表示是否允許發送cookie,默認false;
Access-Control-Max-Age 可選 本次預檢的有效期,單位:秒;

3.1 在Spring Boot 中解決

  • 在spring boot中給我們提供了 @CrossOrigin 註解用於解決跨域問題。

  • 使用場景要求:jdk1.8+、Spring4.2+

  • 只需要在我們需要的controller上加@CrossOrigin

    @RestController
    //實現跨域註解
    //origin="*"代表所有域名都可訪問
    //maxAge飛行前響應的緩存持續時間的最大年齡,簡單來說就是Cookie的有效期 單位爲秒若maxAge是負數,則代表爲臨時Cookie,不會被持久化,Cookie信息保存在瀏覽器內存中,瀏覽器關閉Cookie就消失
    @CrossOrigin(origins = "*",maxAge = 3600)
    @RequestMapping("/album")
    public class AlbumController {}
    

3.2 在spring Cloud中解決

只需要在spring Cloud Gateway 服務中添加配置就行

spring:
  application:
    name: system-gateway
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有請求
            allowedOrigins: "*" #跨域處理 允許所有的域
            allowedMethods: # 支持的方法
            - GET
            - POST
            - PUT
            - DELETE

當然也可以自己利用Gateway的攔截器來手動添加相應的頭信息

default-filters:
      - AddResponseHeader=Access-Control-Allow-Credentials,true
      - AddResponseHeader=Access-Control-Allow-Headers,access-control-allow-origin
      - AddResponseHeader=Access-Control-Allow-Methods,GET
      - AddResponseHeader=Access-Control-Allow-Origin,*
      - AddResponseHeader=Access-Control-Allow-Age,3600

3.3 在Nginx中解決

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

  • 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 方法和添加允許源來解決。

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