webpack(六)——webpack 解決跨域的原理


一 什么是跨域?

  主要是由於瀏覽器的同源策略引用的,同源策略是瀏覽器的安全機制,當協議域名端口三者有一個不同,瀏覽器就禁止訪問資源。

  如下 url 上的源是:http://www.company.com:80

  如果地址里面的協議,域名,端口號都相同就是屬於同源的。

  *  http://www.a.com/dir/page.html ----成功

  *  http://www.child.a.com/test/index.html ----失敗,域名不同

  *  https://www.a.com/test/index.html ----失敗,協議不同

  *  http://www.a.com:8080/test/index.html ----失敗,端口號不同

不受同源策略限制的有:

  * 頁面中的連接,重定向以及表單的提交是不會收到同源策略的影響的;

  * 跨域資源的引入是可以的,但是js不能讀寫加載的內容,如嵌套到頁面中的<script src='....'></script>,<img>,<link>,<iframe>

  

嚴格的來講:瀏覽器並不是全部禁止跨域資源的請求,它只是禁止對跨越資源的讀操作。瀏覽器的同源限制策略是這樣的:

  * 瀏覽器允許跨域寫操作,如連接,重定向;

  * 瀏覽器允許跨域資源嵌入,如img,script標簽。

  * 瀏覽器不允許跨域讀操作

 

二 解決跨域的方法?

  最常用的解決跨域的常用的方法有JSONP,CORS

(1)使用JSONP來解決跨域

  實現原理:a.com/jsonp.html 想要得到 b.com/main.js 里面的數據,可以在 jsonp.html 里面創建一個回調函數 xxx,動態的添加 <script>元素,向服務器發送請求,請求地址后面提那就上查詢的字符串,通過回調函數callback 參數指定回調函數的名稱,請求地址為 http://b.com/main.js?callbcak=xxx,在main 里面調用這個回調函數xxx ,並且一JSON數據形式作為參數傳遞,完成回調

// jsonp.html

// 創建一個script標簽
function addScriptTag(src){
  var script=document.createElement('script');
  script.setAttribute('type','text/javascript');
  script.src=src
  document.body.appendChild(script);
}
// 頁面加載完畢后創建一個script標簽
window.onload=function(){
  addScriptTag('http://b.com/main.js?callback=foo');
}

function foo(data){
  console.log(data.name+'歡迎你')
}

main.js里面的代碼:

foo({name:'張三'})

JSONP 方法的缺點:

  * 使用這種方法,只要是個網站都可以拿到 b.com 里面的數據,存在着安全性的問題;

  * 只能發送get 請求,不能發送 POST 請求;

  * 可能會被注入惡意代碼,篡改頁面內容,可以采用字符串過濾來規避此問題。

(相關鏈接:)

(2)使用CORS 來解決此方法

  CORS 是一個W3C標准,全稱是跨域資源共享,它允許瀏覽器向跨域資源服務器,發起 XMLHttpRequest 請求,從而克服了AJAX 只能同源使用的限制。

  在剛才的列子里面,可以在 b.com 里面添加響應頭允許 a.com 的訪問,代碼如下:

    Access-Control-Allow-Origin:http://a.com

  然后a.com 就可以用ajax 獲取 b.com 里的數據了。

三 webpack解決跨域?

  webpack proxy ,就是 webpack 提供的解決跨域的方案。

  其基本行為是接受客戶端發送的請求后轉發給其他的服務器,目的是為了便於開發者在開發的模式下解決跨域的問題

  要想實現代理必須要一個中間服務器, webpack 提供服務器的工具是 webpack-dev-server,只適用於開發階段。

  可以在webpack 配置對象屬性中通過 devServer 屬性來配置:如下

// ./webpack.config.js
const path = require('path')

module.exports = {
    // ...
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        port: 9000,
        proxy: {
            '/api': {
                target: 'https://api.github.com'
            }
        }
        // ...
    }
}

  devServer 里面的 proxy 就是關於代理的配置,該屬性是一個對象,對象中的每一個規則就是一個代理的規則匹配,屬性的名稱是需要被代理的請求路徑前綴,一般為了辨別都會被設置為 /api ,值為對象的代理匹配規則,對應如下:

  * target : 表示的是代理到的目標地址

  * pathRewrite: 默認情況下,我們的 /api-hy 也會被寫到 RUL 中,如果希望刪除,可以使用 pathRewrite 

  * secure :默認情況下不接受轉發到 https 的服務器上的,如果希望支持,可以設置為 false

  * changeOrigin: 它是表示是否更新代理后請求的 headers 中的 host 地址

四 工作原理

  proxy 工作原理上市利用 http-proxy-middleware 這個http 代理中間件,實現請求轉發給其他的服務器。如下:在開發階段,本地地址是 Http://loaclhost:3000 , 該瀏覽器發送一個前綴帶有 /api 標識的向服務器請求數據,但是這個服務器只是將這個請求轉發給另一台服務器:

const express = require('express');
const proxy = require('http-proxy-middleware');

const app = express();

app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true}));
app.listen(3000);

// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar

  在開發階段,webpack-dev-server 會自動啟動一個本地開發服務器,所以我們的應用在開發階段是獨立運行在 localhost 的一個端口上的,而后端服務器又是運行在另一個地址上

  所以在開發階段中,由於瀏覽器的同源策略,當本地訪問的時候就會出現跨域資源請求的問題,通過設置 webpack proxy 實現代理請求后,相當於瀏覽器和服務器之間添加了一個代理着。當本地發送請求的時候,中間服務器會接受這個情求,並將這個請求轉發給目標服務器,目標服務器返回數據后,中間服務器又會將數據返回給瀏覽器,當中間服務器將數據返回給服務器的時候,它們兩者是同源的,並不會存在跨域的問題。

  服務器和服務器之間是不會存在跨域資源的問題的。

參考文章:

https://mp.weixin.qq.com/s/6nQ-m9HL3-FENv6vF4dOnQ
https://www.cnblogs.com/rockmadman/p/6836834.html,
https://juejin.cn/post/6844903496521613320

 


免責聲明!

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



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