成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

「跨域」利用node.js實(shí)踐前端各種跨域方式(上)

Lavender / 359人閱讀

摘要:如果對(duì)你有幫助的話,歡迎一跨域首先我們?cè)诒镜仄鹨粋€(gè)服務(wù)器,用于接收客戶(hù)端的請(qǐng)求并作出回應(yīng)。五跨域原理域想和域通信,通過(guò)中間頁(yè)面。即借助接收到了發(fā)來(lái)的消息,并給予回應(yīng)跨域成功接下文跨域利用實(shí)踐前端各種跨域方式下

前言

常言道,"讀萬(wàn)卷書(shū),不如行萬(wàn)里路"。技術(shù)的學(xué)習(xí)也是如此,唯有實(shí)踐才能更清楚的明白原理和加深印象,因此本文會(huì)利用node.js對(duì)前端的各種跨域方式進(jìn)行實(shí)踐,強(qiáng)烈建議一步一步跟著做,相信你肯定會(huì)對(duì)跨域有更深層次的理解。而由于篇幅限制,本文只會(huì)貼出關(guān)鍵性的代碼,本系列總共分為上下篇。具體的代碼請(qǐng)移步我的Github。如果對(duì)你有幫助的話,歡迎 star ヾ(′?ω?`)?

一、cors 跨域

首先我們?cè)诒镜仄鹨粋€(gè)服務(wù)器,用于接收客戶(hù)端的請(qǐng)求并作出回應(yīng)。

//目錄:cors/server.js

const http = require("http");

http.createServer(function (req, res) {
    //設(shè)置響應(yīng)頭部
    res.writeHead(200, {"Content-Type": "text/plain"});
    res.write("This is a server page");
    res.end();
  }).listen(3333);
   console.log("server start!")

然后,開(kāi)啟另一個(gè)服務(wù),服務(wù)里加載一個(gè)html頁(yè)面,頁(yè)面對(duì)發(fā)出xhr請(qǐng)求,模擬瀏覽器對(duì)服務(wù)器的請(qǐng)求。

//目錄:cors/clientServer.js

const express = require("express");
const app = express();

app.use(express.static("./public"));
app.listen(3000)
console.log("client server start");

//目錄:cors/public/client.html

            const  content = document.getElementById("content");

            const xhr = new XMLHttpRequest();
            xhr.withCredentials = true;
            xhr.onload = function(){
                if(xhr.readyState == 4) {
                    if(xhr.status >= 200 && xhr.status <300 || xhr.status == 304) {
                        content.innerHTML = "Reuqest was success:" + xhr.responseText;
                        console.log("Request was success:", xhr.responseText);
                    }else {
                        content.innerHTML = "Reuqest was failed:" + xhr.status;
                        console.log("Request was failed:", xhr.status); 
                    }
                }
            }
            // xhr.open("get", "http://localhost:3000/client.html", true); //不跨域
            xhr.open("get", "http://localhost:3333", true); //跨域

            xhr.send();

分別運(yùn)行兩個(gè)服務(wù),測(cè)試3000和3333接口,發(fā)現(xiàn)只有跨域的時(shí)候,請(qǐng)求的頭部才會(huì)帶著origin字段。此時(shí)我們修改cors/server.js, 加上這行代碼:

    res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");

這行代碼代表服務(wù)器允許接收來(lái)自3000接口的請(qǐng)求,此時(shí)客戶(hù)端再次請(qǐng)求服務(wù)器,就能在用戶(hù)毫無(wú)感知的情況下完成跨域。

而此時(shí)如果想讓客戶(hù)端帶cookie請(qǐng)求呢?那么需要做以下工作:

1.cors/server.js 加上這行

    res.setHeader("Access-Control-Allow-Credentials", true);

2.cors/public/client.html 加上這行

xhr.withCredentials = true;

然后,你就會(huì)發(fā)現(xiàn),客戶(hù)端會(huì)把當(dāng)前域下的cookie一起發(fā)給服務(wù)器啦╮( ̄▽?zhuān)?)╭

ps:注意cookie只能細(xì)分到域名下,不能細(xì)分到端口。即沒(méi)辦法設(shè)置一個(gè)cookie僅在localhost:xxxx下。盡管端口不同會(huì)被瀏覽器認(rèn)為不同源。
二、jsonp跨域

通常為了減輕web服務(wù)器的負(fù)載,我們把js、css,img等靜態(tài)資源分離到另一臺(tái)獨(dú)立域名的服務(wù)器上,在html頁(yè)面中再通過(guò)相應(yīng)的標(biāo)簽從不同域名下加載靜態(tài)資源,而被瀏覽器允許,基于此原理,我們可以通過(guò)動(dòng)態(tài)創(chuàng)建script,再請(qǐng)求一個(gè)帶參網(wǎng)址實(shí)現(xiàn)跨域通信。

下面這個(gè)例子采用jQuery中的ajax方法,與服務(wù)器端約定將數(shù)據(jù)回傳到回調(diào)函數(shù)中,比如本例中的callback=person,然后我們就可以從回調(diào)函數(shù)person里獲取服務(wù)器傳給瀏覽器的數(shù)據(jù)了。另外,jsonp的缺點(diǎn)就是只能采用get請(qǐng)求。

1.目錄:jsonp/server.js

const http = require("http");
const urllib = require("url");
const  httpdispatcher = require("httpdispatcher");
const dispatcher = new httpdispatcher();

const PORT = 1112;

function handleRequest(req, res) {
    try {
        console.log(req.url);

        dispatcher.dispatch(req, res);
    }catch(err) {
        console.log(err);
    }
}

const server = http.createServer(handleRequest);

dispatcher.onGet("/getPerson", function (req, res, next) {
  const data = {"name": "Jchermy", "company": "dog company"};
  const params = urllib.parse(req.url, true);

  if(params.query && params.query.callback) {
      let str = `${params.query.callback}(${JSON.stringify(data)})`;
      res.write(str);
      res.end();
  }else {
      res.write(JSON.stringify(data));
      res.end();
  }
})

server.listen(PORT, function () {
    console.log("server listening on http://localhost: %s", PORT);
  })

2.目錄:jsonp/client.js

const express = require("express");
const app = express();

app.use(express.static("./public"));
app.listen(1111);
console.log("client start");

3.目錄:jsonp/public/index.html




    
    
    
    index
    


    
    
姓名:
公司:

分別運(yùn)行客戶(hù)端和服務(wù)端,點(diǎn)擊“獲取跨域數(shù)據(jù)的按鈕”,當(dāng)前頁(yè)面(1111端口)就可以拿到1112端口的數(shù)據(jù)啦~~(●′ω`●)

三、document.domain + frame 跨域

此方案僅限主域相同,子域不同的跨域應(yīng)用場(chǎng)景。

實(shí)現(xiàn)原理:兩個(gè)頁(yè)面都通過(guò)js強(qiáng)制設(shè)置document.domain為基礎(chǔ)主域,就實(shí)現(xiàn)了同域。

下面只是舉個(gè)例子幫助大家理解一下。

現(xiàn)在有兩個(gè)網(wǎng)址。百度知道和百度百科

https://zhidao.baidu.com/
https://baike.baidu.com/

在百度知道的網(wǎng)頁(yè),寫(xiě)下以下命令:

document.domain = "baidu.com";
const child= window.open("https://baike.baidu.com/");

在打開(kāi)的百度百科的網(wǎng)頁(yè),寫(xiě)下以下命令:

document.domain = "baidu.com";

然后回到百度知道的網(wǎng)頁(yè),就可以獲取到百度百科(子頁(yè)面)的元素啦:

const button = other.document.getElementById("search");

//
四、window.name+iframe 跨域
window.name屬性的獨(dú)特之處:name值在不同的頁(yè)面(甚至不同域名)加載后依舊存在,并且可以支持非常長(zhǎng)的 name 值(2MB)。

在本地起兩個(gè)node服務(wù),分別占用3333和4444。父頁(yè)面是:
1.window-name/public/index.html

          const proxy = function(url ,callback) {
                let status = 0;
                const iframe = document.createElement("iframe");

                iframe.src = url;

                iframe.onload = function(){
                    if(status === 1) {
                        callback(iframe.contentWindow.name);
                        destoryFrame();
                    } else if (status === 0) {
                        iframe.contentWindow.location = "http://localhost:4444/proxy.html";
                        status = 1;
                    }
                }

                document.body.appendChild(iframe);
          };
         

          function destoryFrame() {
              iframe.contentWindow.document.write("");
              iframe.contentWindow.close();
              document.body.removeChild(iframe);
          }

          proxy("http://localhost:3333/iframe.html", function(data) {
              alert(data);
          })

2.iframe 頁(yè)面是
window-name/public/iframe.html

    

3.還有一個(gè)代理頁(yè)面,跟父頁(yè)面同源。內(nèi)容為空就好。目錄:/window-name/public/proxy.html

總結(jié):通過(guò)iframe的src屬性由外域轉(zhuǎn)向本地域,跨域數(shù)據(jù)即由iframe的window.name從外域傳遞到本地域。這個(gè)就巧妙地繞過(guò)了瀏覽器的跨域訪問(wèn)限制,但同時(shí)它又是安全操作。

五、location.hash+iframe 跨域

原理:A域想和B域通信,通過(guò)中間頁(yè)面c。不同域之間通過(guò)location.hash來(lái)通信,而相同域之間直接通過(guò)js來(lái)通信。

實(shí)現(xiàn):A域:a.html ----> B域:b.html ----> A域:c.html,a與b不同域只能通過(guò)hash值單向通信,b與c也不同域也只能單向通信,但c與a同域,所以c可通過(guò)parent.parent訪問(wèn)a頁(yè)面所有對(duì)象。

目錄:location-hash/public/a.html




    
    
    
    a
    


    

目錄:location-hash/public/b.html




    
    
    
    b
    


    


目錄:location-hash/public/c.html

    

然后,我們通過(guò)node服務(wù)將a.html和c.html部署在同一個(gè)端口下,將b.html部署在另一個(gè)端口。

//location-hash/server1.js
app.use("/a.html", express.static(__dirname+"/public/a.html"));
app.use("/c.html", express.static(__dirname+"/public/c.html"));
app.listen(3333);

//location-hash/server2.js
app.use("/b.html", express.static(__dirname+"/public/b.html"));
app.listen(4444);

最后,我們分別將兩個(gè)服務(wù)跑起來(lái)。訪問(wèn)localhost:3333可以看到彈窗。

即b.html借助c.html接收到了a.html發(fā)來(lái)的消息,并給予回應(yīng)"hello admin",跨域成功~

接下文--->「跨域」利用node.js實(shí)踐前端各種跨域方式(下)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95428.html

相關(guān)文章

  • 跨域利用node.js實(shí)踐前端各種跨域方式

    摘要:如果對(duì)你有幫助的話,歡迎一跨域首先我們?cè)诒镜仄鹨粋€(gè)服務(wù)器,用于接收客戶(hù)端的請(qǐng)求并作出回應(yīng)。五跨域原理域想和域通信,通過(guò)中間頁(yè)面。即借助接收到了發(fā)來(lái)的消息,并給予回應(yīng)跨域成功接下文跨域利用實(shí)踐前端各種跨域方式下 前言 常言道,讀萬(wàn)卷書(shū),不如行萬(wàn)里路。技術(shù)的學(xué)習(xí)也是如此,唯有實(shí)踐才能更清楚的明白原理和加深印象,因此本文會(huì)利用node.js對(duì)前端的各種跨域方式進(jìn)行實(shí)踐,強(qiáng)烈建議一步一步跟著做...

    jaysun 評(píng)論0 收藏0
  • 跨域利用node.js實(shí)踐前端各種跨域方式(下)

    摘要:技術(shù)的學(xué)習(xí)也是如此唯有實(shí)踐才能更清楚的明白原理和加深印象,因此本文會(huì)利用對(duì)前端的各種跨域方式進(jìn)行實(shí)踐,強(qiáng)烈建議一步一步跟著做,相信你肯定會(huì)對(duì)跨域有更深層次的理解。 前言 常言道,讀萬(wàn)卷書(shū),不如行萬(wàn)里路。技術(shù)的學(xué)習(xí)也是如此,唯有實(shí)踐才能更清楚的明白原理和加深印象,因此本文會(huì)利用node.js對(duì)前端的各種跨域方式進(jìn)行實(shí)踐,強(qiáng)烈建議一步一步跟著做,相信你肯定會(huì)對(duì)跨域有更深層次的理解。而由于篇...

    Jenny_Tong 評(píng)論0 收藏0
  • 前端相關(guān)大雜燴

    摘要:希望幫助更多的前端愛(ài)好者學(xué)習(xí)。前端開(kāi)發(fā)者指南作者科迪林黎,由前端大師傾情贊助。翻譯最佳實(shí)踐譯者張捷滬江前端開(kāi)發(fā)工程師當(dāng)你問(wèn)起有關(guān)與時(shí),老司機(jī)們首先就會(huì)告訴你其實(shí)是個(gè)沒(méi)有網(wǎng)絡(luò)請(qǐng)求功能的庫(kù)。 前端基礎(chǔ)面試題(JS部分) 前端基礎(chǔ)面試題(JS部分) 學(xué)習(xí) React.js 比你想象的要簡(jiǎn)單 原文地址:Learning React.js is easier than you think 原文作...

    fuyi501 評(píng)論0 收藏0
  • 20170917 前端開(kāi)發(fā)周報(bào):JavaScript函數(shù)式編程、作用域和閉包

    摘要:用函數(shù)式編程對(duì)進(jìn)行斷舍離當(dāng)從業(yè)的老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了的特性,也不用面向?qū)ο罅耍詈蟀l(fā)現(xiàn)了真愛(ài)啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數(shù)式編程的同學(xué),能快速切入到函數(shù)式編程的理念。 1、用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅耍詈蟀l(fā)現(xiàn)了真愛(ài)?。。?! https:/...

    tomener 評(píng)論0 收藏0
  • 20170917 前端開(kāi)發(fā)周報(bào):JavaScript函數(shù)式編程、作用域和閉包

    摘要:用函數(shù)式編程對(duì)進(jìn)行斷舍離當(dāng)從業(yè)的老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛(ài)啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數(shù)式編程的同學(xué),能快速切入到函數(shù)式編程的理念。 1、用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛(ài)?。。?! https:/...

    cyixlq 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<