跨域的三種解決方式


跨域問題

跨域問題對於WEB前端工程師來說是比較重要的一個問題,因為我們時常需要去解決這樣的問題,在其他類型的前端開發來說,他們並沒有跨域問題

跨域問題的產生

因為瀏覽器有同源策略:只有在同域名,同端口,同協議的情況下才可以進行數據交互;

有的時候,例如,在公司開發項目的時候,前端開發的服務器可能和后端服務器不是同一個,因為可能是通過gulp、webpack搭建的開發服務器,就需要解決跨域問題,再例如,在大公司有,數據服務器不只有一個,所以跨域問題也必然存在

解決方法

jsonp

是一種前后端結合的跨域方式,原理就是通過script標簽的src屬性來進行數據請求,因為其不受同源策略的影響,故而能請求到數據,需要注意的是,數據處理需要通過回調函數來進行,而本質上,我們把回調函數的名字告訴后端,后端將數據放入到回調函數里,所以說需要告知后端,回調函數是什么,這也就是為什么說是前后端結合的方式。

注意:一個script只能請求一次,多次請求應該去動態的創建script,回調函數也只能使用一次,所以也需要動態創建 ,使用完成后移除,避免污染全局空間

缺點:只能get請求

 

nodejs:

  app.get('/data', function (req, res) {

      //后端的任務,就是把數據放到前端的那個函數里並給它執行一下

      //直接返回這個操作的js字符串,因為這個字符串會被script當成js代碼來運行

      //前端回調函數的名字

      let fn = req.query['callback']

      var content = fs.readFileSync('./datas/data.json')+''

      //返回給前端函數數據

      res.send(fn+'('+content+')');

  });

 

  js:

  Jsonp({

      url:"http://localhost:3000/data",

      success(results){

          console.log(results)

      }

  })

  function Jsonp({url,success}) {

      //動態創建script標簽

      let $script = $("<script>")

 

      //隨機函數名字

      var random_name = 'random_fn_'+Date.now()

      //創建的隨機全局函數

      window[random_name] = function(data){

          success(data)

          //處理完數據之后,將script刪掉,函數delete掉

          $script.remove()

          delete window[random_name]

 

      }

      $script[0].src = url+'?callback='+random_name

      $("body").append($script)  

  }

cors

純后端的解決方式,每次請求都會有一個origin信息被后端捕捉,后端可以通過設置對這個origin的域允許訪問來解決跨域問題

node:

   app.get("/data_cors",(req,res)=>{

       //此次請求的源信息

       var reqOrigin = req.header("origin");  

       //如果源信息存在,且源是運行訪問的

       if(reqOrigin !=undefined && reqOrigin.indexOf("http://localhost:9000") > -1){ 

       //設置允許 http://localhost:3000 這個域響應 

       res.header("Access-Control-Allow-Origin", "http://localhost:9000");  //允許這個域訪問

       res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  //允許的請求方法

       res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With"); 

       } 

       res.send('123')

   })

 

   js:

   $.ajax({

       url:"http://localhost:3000/data_cors",

       success(results){

           console.log(results)

       }

   })

服務端代理proxy

因為服務器間的數據交互沒有跨域限制,所以我們可以通過一個中間代理服務器來請求目標服務器的數據,也就是開發服務器發送請求到代理服務器,代理服務器再請求目標服務器,將數據返回給開發服務器

目標服務器接口 3000:

  app.get("/data_proxy",(req,res)=>{

      //此次請求的源信息

      res.send('proxy')

  })

 

  代理服務器1234:

  app.get("/to3000",(req,res)=>{

      //代理服務器1234對9000做跨域處理

      var reqOrigin = req.header("origin");  

      //如果源信息存在,且源是運行訪問的

      if(reqOrigin !=undefined && reqOrigin.indexOf("http://localhost:9000") > -1){ 

      //設置允許 http://localhost:3000 這個域響應 

      res.header("Access-Control-Allow-Origin", "http://localhost:9000");  //允許這個域訪問

      res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  //允許的請求方法

      res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With"); 

      }

      //獲取到9000真正要調用的3000目標服務器的接口

      var url = req.query['url']

      let _res = res

      //代理服務器1234像目標服務器3000發送請求(沒有跨域限制)

      http.get(url,(res)=>{

          let result=''

          res.on("data",(chunk)=>{

              result+=chunk

          })

          res.on("end",()=>{

              console.log(result)

              //代理服務器1234將請求到的目標服務器3000的數據返回給開發服務器9000

              _res.send(result)

          })

      })

  })

  app.listen(1234);

 

  開發服務器9000:

  //當前服務器9000向代理服務器1234發送請求

  $.ajax({

      url:"http://localhost:1234/to3000",

      data:{

          url:"http://localhost:3000/data_proxy"

      },

      success(results){

          console.log(results)

      }

  })


免責聲明!

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



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