天天看點

普歌-多種跨域方式以及解決跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)

普歌-跨域及解決跨域(超詳細,面試官都誇贊)

前言:了解如何跨域前,首先了解什麼是跨域
  1. 同源政策

    - 浏覽器的安全政策

    - 協定名、域名、端口号完全一緻

  2. 跨域

    違背同源政策就會産生跨域

  3. 解決跨域

    jsonp(前端設定和後端設定) \ cors(後端設定) \伺服器代理(後端設定)…

當時3月底面試快手是提起這個怎麼解決跨域時,說的面試都稱,說的很詳細,我相信你即使沒實踐過也能很快上手(原話)~~~~但最後挂在二面了😂😂😂

普歌-多種跨域方式以及解決跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)

用jsonp解決跨域(前後端配合設定)

jsonp原理是因為script标簽是沒有同源政策限制,可以跨域的,用動态生成的script标簽;限制的話隻能發送get請求

封裝jsonp函數

//options中又很多參數
      function jsonp(options) {
        //動态建立script标簽
        var script = document.createElement("script"); //拼接字元串的變量
        //進行url參數的拼接,形如name=gl&age=20
        var params = "";
        for (var attr in options.data) {
          params += "&" + attr + "=" + options.data[attr];
        }
        //myJsonp0213212,生成一個函數名(要通過callback傳遞給後端)
        var fnName = "myJsonp" + Math.random().toString().replace(".", "");
        //我們要想辦法将它變成全局函數
        //(變成全局函數的目的在于後端傳回的參數形式是->func({data...})前端能自動執行得到真正的參數)
        window[fnName] = options.success;
        //拼接callback以及參數給後端
        //為script标簽添加src屬性
        script.src = options.url + "?callback=" + fnName + params;
        //将script标簽追加到頁面中
        document.body.appendChild(script);
        //為script标簽添加onload事件,在調用完就移除script,不會增加一些多餘的标簽
        script.onload = function () {
          document.body.removeChild(script);
        };
      }
           

進行測試

<body>
     <button id="btn1">點我發送請求</button>     <button id="btn2">
      點我發送請求
    </button>
        
    <script type="text/javascript">
      //擷取按鈕
      var btn1 = document.getElementById("btn1");
      var btn2 = document.getElementById("btn2"); //為按鈕添加點選事件
      btn1.onclick = function () {
        jsonp({
          //請求位址
          url: "http://localhost:3001/better",
          data: {
            name: "lisi",
            age: 30,
          },
          success: function (data) {
            console.log(123);
            console.log(data);
          },
        });
      };
      btn2.onclick = function () {
        jsonp({
          //請求位址
          url: "http://localhost:3001/better",
          success: function (data) {
            console.log(456789);
            console.log(data);
          },
        });
      };

      function jsonp(options) {
        //動态建立script标簽
        var script = document.createElement("script"); //拼接字元串的變量
        //
        var params = "";
        for (var attr in options.data) {
          params += "&" + attr + "=" + options.data[attr];
        }
        //myJsonp0213212
        var fnName = "myJsonp" + Math.random().toString().replace(".", "");
        //它已經不是一個全局函數了 
                 //我們要想辦法将它變成全局函數
        window[fnName] = options.success;
                //拼接callback以及參數給後端
        //為script标簽添加src屬性
        script.src = options.url + "?callback=" + fnName + params;
        //将script标簽追加到頁面中
        document.body.appendChild(script);
        //為script标簽添加onload事件,在調用完就移除script,不會增加一些多餘的标簽
        script.onload = function () {
          document.body.removeChild(script);
        };
      }
    </script>
  </body>
           
普歌-多種跨域方式以及解決跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)

我之前也發現百度也使用jsonp發送請求

普歌-多種跨域方式以及解決跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)

CROS跨域(CORS是後端的事)

  • 用戶端(項目中一般都用axios發送請求)
  • 用戶端封裝axios
import axios from "axios";
   import qs from "qs";
   axios.defaults.baseURL = "http://127.0.0.1:3000";
   axios.defaults.timeout = 10000;
     //withCredentials  這個是向伺服器跨域發送請求允不允許攜帶資源憑證(cookie)
   axios.defaults.withCredentials = true;
     /*
      * 設定請求傳遞資料的格式(看伺服器要求什麼格式)
      * x-www-form-urlencoded
      */
   axios.defaults.headers["Content-Type"] =
       "application/x-www-form-urlencoded";
   axios.defaults.transformRequest = (data) => qs.stringify(data);
   //以上還可以寫成對象形式
 /*  const service = axios.create({
     baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
     timeout: 10000 // request timeout
  })*/
    /*
      * 設定請求攔截器
      * TOKEN校驗(JWT):接收伺服器傳回的token,存儲到vuex/本地存儲中,每一次向伺服器發請求,我們應該把token帶上
      */
    axios.interceptors.request.use(
       (config) => {
         let token = localStorage.getItem("token");
         token && (config.headers.Authorization = token);
         return config;
       },
       (error) => {
         return Promise.reject(error);
       }
     );
    /*
      * 響應攔截器
      */
     axios.interceptors.response.use(
       (response) => {
         return response.data;
       },
       (error) => {}
     );
     export default axios;
           

Node服務端設定跨域

//  這裡是node中的做法
app.use((req, res, next) => {
   //  允許哪些源通路,到項目中應用的話可以給一個*(就是所有源),或者填寫某個具體的域
   res.header("Access-Control-Allow-Origin", "*");
   // 允不允許用戶端發送資源憑證 Credentials
   res.header("Access-Control-Allow-Credentials", true);
   // 允許發送哪些請求頭
   res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length,Authorization, Accept,X-Requested-With");
   //允許發送哪些請求
   res.header( "Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS,HEAD");
   // 發送正常請求(post/get等)前會提起發送OPTIONS試探性請求,看看能不能連上伺服器
   req.method === "OPTIONS"? res.send("CURRENT SERVICES SUPPORT CROSS DOMAIN REQUESTS!"): next();
});
           

基于http/https proxy實作跨域請求(開發環境)

  • 配置proxy隻有在開發環境中起作用,因為webpack隻有在開發時用到
  • 第一,配置webpack代理

    打開 webpack 配置檔案,進入開發環境下配置。在module.exports的dev對象下。

  • 如果是 vue cli 3 ,剛進入

    vue.config.js

    。如果沒有vue.config.js檔案,在項目的根目錄下,建立一個。在module.exports的dev對象下配置,也可以在configureWebpack: config=>{ … } 函數内判斷開發環境,然後config.devServer = { 配置資訊 }

配置資訊如下:

module.exports = {
	devServer: {
	    proxy: {
	    //定義請求的基礎URL, 友善跨域請求時使用
	      "/api": {
	      // 目标伺服器位址
	        target: "http://172.16.1.18:8769", 
	        // 開啟代理伺服器,
	        changeOrigin: true,
	         // 将 請求位址字首 /api 替換為 空的,
	        pathRewrite: {
	          "^/api": ""
	        },
            secure: false
	      }
	    }
	  }
}
           

參數解讀:

“/api”: 指接口調用時,遇到接口路徑為 api 時,則代理轉發到 target 的配置url上

target: 開發環境調用的接口位址

changeOrigin:改變源到url,在虛拟主機上很有用

pathRewrite:是指伺服器把接口中api去掉,以免api這幾個字母加入到接口位址中

secure: false, // 接受 運作在 https 上的服務

生産環境中要用nginx反向代理(生産環境)

nginx配置反向代理

普歌-多種跨域方式以及解決跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)
普歌-多種跨域方式以及解決跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)

還有一個iframe跨域,隻不過我沒實戰過…

iframe跨域

普歌-多種跨域方式以及解決跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)

OVER,get到的小夥伴給個三連呗~~~

更多推薦:wantLG的《普歌-頁面優化之實作圖檔懶加載+節流(面試重點)》

  • 作者:wantLG
  • 本文源自:wantLG的《普歌-多種跨域方式以及解決跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)》
  • 本文版權歸作者和CSDN共有,歡迎轉載,且在文章頁面明顯位置給出原文連結,未經作者同意必須保留此段聲明,否則保留追究法律責任的權利。

繼續閱讀