什麼是跨域?及跨域解決方法

2022-09-07 18:01:17

什麼是跨域

當一個請求url的協定、域名、埠三者之間任意一個與當前頁面url不同即為跨域。

跨域指的是瀏覽器不能執行其它網站的指令碼。是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript 施加的安全限制。

有一點必須要注意:跨域並不是請求發不出去,請求能發出去,伺服器端能收到請求並正常返回結果,只是結果被瀏覽器攔截了。之所以會跨域,是因為受到了同源策略的限制,同源策略要求源相同才能正常進行通訊,即協定、域名、埠號都完全一致。

什麼是同源策略?

協定號 - 域名 - 埠號 ,只有當這三個條件同時滿足相同時,我們就稱之為符合同源策略,同源策略也可以看做是一個協定。

https://  www.baidu.com   :8080    /test
協定號         域名        埠號    路徑

通常我們導航的url都是由這四部分組成的。

同源策略限制從一個源載入的檔案或指令碼如何與來自另一個源的資源進行互動。這是一個用於隔離潛在惡意檔案的關鍵的安全機制。它的存在可以保護使用者隱私資訊,防止身份偽造等(讀取Cookie)。

同源策略限制行為:

  • CookieLocalStorageIndexDB無法讀取;
  • 無法獲得非同源網頁的 DOM節點;
  • AJAX請求不能傳送;
但是有三個標籤允許跨域載入資源:
<img src=XXX> 
<link href=XXX> 
<script src=XXX>

跨域解決方法

1.Proxy代理

webpack本地代理

【前端解決:只適用於本地開發環境,上線瞭解決不了,直接把dist放在後端伺服器中】

Proxy通過伺服器端介面轉發來實現對於跨域問題的問題,因為HTTP同源策略只在瀏覽器中生效。 這裡介紹幾種不同Proxy代理方法:

在vue.config.js中利用 WebpackDevServer 設定本地代理

// 設定範例:
module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {
        target: 'xxx',
        pathRewrite: {
          '^/api': ''
        },
        changeOrigin: true
      }
    }
  }
};

注意:專案上線需要把打包後的檔案放在伺服器上執行,而不是啟動腳手架執行,也就沒有內建web伺服器做代理,所以此方式只適用於開發測試階段

上線時需要使用nginx代理或者伺服器設定cors(每種語言有自己不同的設定方式)

參考:Vue中如何解決跨域問題

Nginx反向代理

server {
 
    #nginx監聽所有localhost:8080埠收到的請求
    listen       8080;
    server_name  localhost;
 
    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;
    #localhost:8080 會被轉發到這裡
    #同時, 後端程式會接收到 "192.168.25.20:8088"這樣的請求url
    location / {
        proxy_pass http://192.168.25.20:8088;
    }
    #localhost:8080/api/ 會被轉發到這裡
    #同時, 後端程式會接收到 "192.168.25.20:9000/api/"這樣的請求url
    location /api/ {
        proxy_pass http://192.168.25.20:9000;
    }
    error_page 404 /404.html;
        location = /40x.html {
    }
    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

參考:什麼是跨域?及7種跨域解決方法

2.跨域資源共用 CORS

目前最主流、最簡單的方案,直接讓後端設定響應頭,允許資源共用就ok了

CORS 是跨域資源分享(Cross-Origin Resource Sharing)的縮寫。它是 W3C 標準,屬於跨源 AJAX 請求的根本解決方法。

1、普通跨域請求:只需伺服器端設定Access-Control-Allow-Origin
2、帶cookie跨域請求:前後端都需要進行設定

【前端設定】根據xhr.withCredentials欄位判斷是否帶有cookie

vue框架

  • vue-resource
    Vue.http.options.credentials = true
  •  axios
    axios.defaults.withCredentials = true

【伺服器端設定】

伺服器端對於CORS的支援,主要是通過設定Access-Control-Allow-Origin來進行的。如果瀏覽器檢測到相應的設定,就可以允許Ajax進行跨域的存取。若後端設定成功,前端瀏覽器控制檯則不會出現跨域報錯資訊,反之,說明沒設成功。

Java後臺

/*
 * 匯入包:import javax.servlet.http.HttpServletResponse;
 * 介面引數中定義:HttpServletResponse response
 */
 
// 允許跨域存取的域名:若有埠需寫全(協定+域名+埠),若沒有埠末尾不用加'/'
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); 
 
// 允許前端帶認證cookie:啟用此項後,上面的域名不能為'*',必須指定具體的域名,否則瀏覽器會提示
response.setHeader("Access-Control-Allow-Credentials", "true"); 
 
// 提示OPTIONS預檢時,後端需要設定的兩個常用自定義頭
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");

參考:什麼是跨域?及7種跨域解決方法

3.JSONP

JSONP 是伺服器與使用者端跨源通訊的常用方法。最大特點就是簡單適用,相容性好(相容低版本IE),缺點是隻支援get請求,不支援post請求。

核心思想:網頁通過新增一個<script>元素,向伺服器請求 JSON 資料,伺服器收到請求後,將資料放在一個指定名字的回撥函數的引數位置傳回來。

this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})