摘要:如果對你有幫助的話,歡迎一跨域首先我們在本地起一個服務器,用于接收客戶端的請求并作出回應。五跨域原理域想和域通信,通過中間頁面。即借助接收到了發來的消息,并給予回應跨域成功接下文跨域利用實踐前端各種跨域方式下
前言
常言道,"讀萬卷書,不如行萬里路"。技術的學習也是如此,唯有實踐才能更清楚的明白原理和加深印象,因此本文會利用node.js對前端的各種跨域方式進行實踐,強烈建議一步一步跟著做,相信你肯定會對跨域有更深層次的理解。而由于篇幅限制,本文只會貼出關鍵性的代碼,本系列總共分為上下篇。具體的代碼請移步我的Github。如果對你有幫助的話,歡迎 star ヾ(′?ω?`)?
一、cors 跨域首先我們在本地起一個服務器,用于接收客戶端的請求并作出回應。
//目錄:cors/server.js
const http = require("http"); http.createServer(function (req, res) { //設置響應頭部 res.writeHead(200, {"Content-Type": "text/plain"}); res.write("This is a server page"); res.end(); }).listen(3333); console.log("server start!")
然后,開啟另一個服務,服務里加載一個html頁面,頁面對發出xhr請求,模擬瀏覽器對服務器的請求。
//目錄: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();
分別運行兩個服務,測試3000和3333接口,發現只有跨域的時候,請求的頭部才會帶著origin字段。此時我們修改cors/server.js, 加上這行代碼:
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
這行代碼代表服務器允許接收來自3000接口的請求,此時客戶端再次請求服務器,就能在用戶毫無感知的情況下完成跨域。
而此時如果想讓客戶端帶cookie請求呢?那么需要做以下工作:
1.cors/server.js 加上這行
res.setHeader("Access-Control-Allow-Credentials", true);
2.cors/public/client.html 加上這行
xhr.withCredentials = true;
然后,你就會發現,客戶端會把當前域下的cookie一起發給服務器啦╮( ̄▽ ̄")╭
ps:注意cookie只能細分到域名下,不能細分到端口。即沒辦法設置一個cookie僅在localhost:xxxx下。盡管端口不同會被瀏覽器認為不同源。二、jsonp跨域
通常為了減輕web服務器的負載,我們把js、css,img等靜態資源分離到另一臺獨立域名的服務器上,在html頁面中再通過相應的標簽從不同域名下加載靜態資源,而被瀏覽器允許,基于此原理,我們可以通過動態創建script,再請求一個帶參網址實現跨域通信。
下面這個例子采用jQuery中的ajax方法,與服務器端約定將數據回傳到回調函數中,比如本例中的callback=person,然后我們就可以從回調函數person里獲取服務器傳給瀏覽器的數據了。另外,jsonp的缺點就是只能采用get請求。
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 姓名:
公司:
分別運行客戶端和服務端,點擊“獲取跨域數據的按鈕”,當前頁面(1111端口)就可以拿到1112端口的數據啦~~(●′ω`●)
三、document.domain + frame 跨域此方案僅限主域相同,子域不同的跨域應用場景。
實現原理:兩個頁面都通過js強制設置document.domain為基礎主域,就實現了同域。
下面只是舉個例子幫助大家理解一下。
現在有兩個網址。百度知道和百度百科
https://zhidao.baidu.com/ https://baike.baidu.com/
在百度知道的網頁,寫下以下命令:
document.domain = "baidu.com"; const child= window.open("https://baike.baidu.com/");
在打開的百度百科的網頁,寫下以下命令:
document.domain = "baidu.com";
然后回到百度知道的網頁,就可以獲取到百度百科(子頁面)的元素啦:
const button = other.document.getElementById("search"); //四、window.name+iframe 跨域
window.name屬性的獨特之處:name值在不同的頁面(甚至不同域名)加載后依舊存在,并且可以支持非常長的 name 值(2MB)。
在本地起兩個node服務,分別占用3333和4444。父頁面是:
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 頁面是
window-name/public/iframe.html
3.還有一個代理頁面,跟父頁面同源。內容為空就好。目錄:/window-name/public/proxy.html
總結:通過iframe的src屬性由外域轉向本地域,跨域數據即由iframe的window.name從外域傳遞到本地域。這個就巧妙地繞過了瀏覽器的跨域訪問限制,但同時它又是安全操作。
五、location.hash+iframe 跨域原理:A域想和B域通信,通過中間頁面c。不同域之間通過location.hash來通信,而相同域之間直接通過js來通信。
實現:A域:a.html ----> B域:b.html ----> A域:c.html,a與b不同域只能通過hash值單向通信,b與c也不同域也只能單向通信,但c與a同域,所以c可通過parent.parent訪問a頁面所有對象。
目錄:location-hash/public/a.html
a
目錄:location-hash/public/b.html
b
目錄:location-hash/public/c.html
然后,我們通過node服務將a.html和c.html部署在同一個端口下,將b.html部署在另一個端口。
//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);
最后,我們分別將兩個服務跑起來。訪問localhost:3333可以看到彈窗。
即b.html借助c.html接收到了a.html發來的消息,并給予回應"hello admin",跨域成功~
接下文--->「跨域」利用node.js實踐前端各種跨域方式(下)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/39966.html
摘要:如果對你有幫助的話,歡迎一跨域首先我們在本地起一個服務器,用于接收客戶端的請求并作出回應。五跨域原理域想和域通信,通過中間頁面。即借助接收到了發來的消息,并給予回應跨域成功接下文跨域利用實踐前端各種跨域方式下 前言 常言道,讀萬卷書,不如行萬里路。技術的學習也是如此,唯有實踐才能更清楚的明白原理和加深印象,因此本文會利用node.js對前端的各種跨域方式進行實踐,強烈建議一步一步跟著做...
摘要:技術的學習也是如此唯有實踐才能更清楚的明白原理和加深印象,因此本文會利用對前端的各種跨域方式進行實踐,強烈建議一步一步跟著做,相信你肯定會對跨域有更深層次的理解。 前言 常言道,讀萬卷書,不如行萬里路。技術的學習也是如此,唯有實踐才能更清楚的明白原理和加深印象,因此本文會利用node.js對前端的各種跨域方式進行實踐,強烈建議一步一步跟著做,相信你肯定會對跨域有更深層次的理解。而由于篇...
摘要:用函數式編程對進行斷舍離當從業的老司機學會函數式編程時,他扔掉了的特性,也不用面向對象了,最后發現了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數式編程的同學,能快速切入到函數式編程的理念。 1、用函數式編程對JavaScript進行斷舍離 當從業20的JavaScript老司機學會函數式編程時,他扔掉了90%的特性,也不用面向對象了,最后發現了真愛啊!!! https:/...
摘要:用函數式編程對進行斷舍離當從業的老司機學會函數式編程時,他扔掉了的特性,也不用面向對象了,最后發現了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數式編程的同學,能快速切入到函數式編程的理念。 1、用函數式編程對JavaScript進行斷舍離 當從業20的JavaScript老司機學會函數式編程時,他扔掉了90%的特性,也不用面向對象了,最后發現了真愛啊!!! https:/...
閱讀 813·2021-11-18 10:02
閱讀 2503·2021-11-11 16:54
閱讀 2750·2021-09-02 09:45
閱讀 654·2019-08-30 12:52
閱讀 2774·2019-08-29 14:04
閱讀 2745·2019-08-29 12:39
閱讀 448·2019-08-29 12:27
閱讀 1887·2019-08-26 13:23