摘要:一同源策略瀏覽器出于安全方面的考慮,只允許與本域下的接口交互。包括發(fā)送信息的內(nèi)容,發(fā)送信息的域名等等同樣的,在內(nèi)添加一個事件監(jiān)聽綁定事件,在內(nèi)通過方法發(fā)送信息給一樣可以進行跨域通信
一、同源策略(Same origin Policy)
瀏覽器出于安全方面的考慮,只允許與本域下的接口交互。不同源的客戶端腳本在沒有明確授權(quán)的情況下,不能讀寫對方的資源。
1、同源(本域)所謂“同源”指的是”三個相同“。相同的域名、端口和協(xié)議,這三個相同的話就視為同一個域,本域下的JS腳本只能讀寫本域下的數(shù)據(jù)資源,無法訪問其它域的資源。
協(xié)議相同 (都是http或者https)
域名相同 (都是http://jirengu.com/a> 和 和...
不同源情況:
http://jirengu.com/main.js> 和 https://jirengu.com/a.php (協(xié)議不同)
http://jirengu.com/main.js> 和 http://bbs.jirengu.com/a.php (域名不同,域名必須完全相同才可以)
http://jiengu.com/main.js> 和... (端口不同,第一個是80)
2、Ajax 跨域報錯實例(1)修改host文件:給host文件里添加兩條記錄,方便跨域操作
上圖意思是訪問 a.com 或是 b.com 相當于訪問本機, 可以實現(xiàn)一個場景:瀏覽器是a.com,而接口是b.com,雖說最終對應(yīng)的是本機,但是域名不一樣
(2)建一個index.html文件,獲取數(shù)據(jù)
hello world
(3)建一個server.js文件,實現(xiàn)靜態(tài)文件、動態(tài)路由功能
var http = require("http") var fs = require("fs") var path = require("path") var url = require("url") http.createServer(function(req, res){ var pathObj = url.parse(req.url, true) switch (pathObj.pathname) { case "/getWeather": res.end(JSON.stringify({beijing: "sunny"})) break; default: fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){ if(e){ res.writeHead(404, "not found") res.end("404 Not Found
") }else{ res.end(data) } }) } }).listen(8080)
(4)執(zhí)行結(jié)果
打開終端,cd 到當前文件夾,然后輸入node server.js,啟動靜態(tài)服務(wù)器
A、瀏覽器地址欄輸入localhost:8080/index.html ,獲取到了數(shù)據(jù)
B、瀏覽器地址改為127.0.0.1:8080/index.html,就報錯啦,因為當前域名和請求域名不一樣
C、如果瀏覽器改成a.com或是b.com 也是會報錯的,就算它們都是指向同一個本機
總結(jié)一下:只有在請求域名和當前域名相同的情況下,才能獲取數(shù)據(jù),才不會報錯。
注:跨域的資源內(nèi)嵌是被允許的,對于當前頁面來說頁面存放的 JS 文件的域不重要,重要的是加載該 JS 頁面所在什么域
二、跨域解決同源策略帶來的不便,突破同源策略的限制去獲取不同源之間的數(shù)據(jù)信息或者進行不同源之間的信息傳遞。
解決辦法 1? JSONPHTML 中 script 標簽可以加載其他域下的js,比如我們經(jīng)常引入一個其他域下線上cdn的jQuery。
可以這樣子實現(xiàn)從其他域下獲取數(shù)據(jù)
這時候會向天氣接口發(fā)送請求獲取數(shù)據(jù),獲取數(shù)據(jù)后做為 js 來執(zhí)行。 但這里有個問題, 數(shù)據(jù)是 JSON 格式的數(shù)據(jù),直接作為 JS 運行的話,如何去得到這個數(shù)據(jù)來操作呢?
此時需要后端的配合,因為后端的接口需要根據(jù)約定的參數(shù)獲取回調(diào)函數(shù)名,然后跟返回數(shù)據(jù)進行拼接,最后進行響應(yīng)
這個請求到達后端后,后端會去解析callback這個參數(shù)獲取到字符串showData,在發(fā)送數(shù)據(jù)做如下處理:
之前后端返回數(shù)據(jù): {"city": "hangzhou", "weather": "晴天"}
現(xiàn)在后端返回數(shù)據(jù): showData({"city": "hangzhou", "weather": "晴天"})
前端script標簽在加載數(shù)據(jù)后會把 「showData({“city”: “hangzhou”, “weather”: “晴天”})」做為 js 來執(zhí)行。
這實際上就是調(diào)用showData這個函數(shù),同時參數(shù)是 {“city”: “hangzhou”, “weather”: “晴天”}。
當然前端提前在頁面定義好showData這個全局函數(shù),在函數(shù)內(nèi)部處理參數(shù)即可。
(1)JSONP是通過 script 標簽加載數(shù)據(jù)的方式去獲取數(shù)據(jù)當做 JS 代碼來執(zhí)行
(2)提前在頁面上聲明一個函數(shù),函數(shù)名通過接口傳參的方式傳給后臺,后臺解析到函數(shù)名后在原始數(shù)據(jù)上「包裹」這個函數(shù)名,發(fā)送給前端。
換句話說,JSONP 需要對應(yīng)接口的后端的配合才能實現(xiàn)
舉個例子
server.js 文件
var http = require("http") var fs = require("fs") var path = require("path") var url = require("url") http.createServer(function(req, res){ var pathObj = url.parse(req.url, true) switch (pathObj.pathname) { case "/getNews": var news = [ "第11日前瞻:中國沖擊4金 博爾特再戰(zhàn)200米羽球", "正直播柴飚/洪煒出戰(zhàn) 男雙力爭會師決賽", "女排將死磕巴西!郎平安排男陪練模仿對方核心" ] res.setHeader("Content-Type","text/json; charset=utf-8") if(pathObj.query.callback){ res.end(pathObj.query.callback + "(" + JSON.stringify(news) + ")") }else{ res.end(JSON.stringify(news)) } break; default: fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){ if(e){ res.writeHead(404, "not found") res.end("404 Not Found
") }else{ res.end(data) } }) } }).listen(8080)
html文件
打開終端,cd 到當前文件夾,然后輸入node server.js,啟動靜態(tài)服務(wù)器
顯示結(jié)果:
圖中Request URL :http://127.0.0.1:8080/getNews?callback=appendHtml 會向瀏覽器發(fā)請求,得到數(shù)據(jù),然后當成 js 去執(zhí)行,因為頁面上已經(jīng)有了appendHtml函數(shù),然后去執(zhí)行這個函數(shù),把appendHtml 括號里的內(nèi)容作為參數(shù)傳遞進去
2、CORS全稱是跨域資源共享(Cross-Origin Resource Sharing),是一種 ajax 跨域請求資源的方式,支持現(xiàn)代瀏覽器,IE支持10以上。
實現(xiàn)方式:
當你使用 XMLHttpRequest 發(fā)送請求時,瀏覽器發(fā)現(xiàn)該請求不符合同源策略,會給該請求加一個請求頭:Origin,后臺進行一系列處理:
(1)如果確定接受請求則在返回結(jié)果中加入一個響應(yīng)頭:Access-Control-Allow-Origin; 瀏覽器判斷該相應(yīng)頭中是否包含 Origin 的值。
(2)如果有則瀏覽器會處理響應(yīng),我們就可以拿到響應(yīng)數(shù)據(jù)。
(3)如果不包含瀏覽器直接駁回,這時我們無法拿到響應(yīng)數(shù)據(jù)。
所以 CORS 的表象是讓你覺得它與同源的 ajax 請求沒啥區(qū)別,代碼完全一樣。
舉個例子
server.js文件
var http = require("http") var fs = require("fs") var path = require("path") var url = require("url") http.createServer(function(req, res){ var pathObj = url.parse(req.url, true) switch (pathObj.pathname) { case "/getNews": var news = [ "第11日前瞻:中國沖擊4金 博爾特再戰(zhàn)200米羽球", "正直播柴飚/洪煒出戰(zhàn) 男雙力爭會師決賽", "女排將死磕巴西!郎平安排男陪練模仿對方核心" ] res.setHeader("Access-Control-Allow-Origin","http://localhost:8080") //訪問控制允許的域 http://localhost:8080 //res.setHeader("Access-Control-Allow-Origin","*") res.end(JSON.stringify(news)) break; default: fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){ if(e){ res.writeHead(404, "not found") res.end("404 Not Found
") }else{ res.end(data) } }) } }).listen(8080)
index.html文件
顯示結(jié)果
(1)輸入http://127.0.0.1:8080/index.html 發(fā)送請求時,不需要跨域,請求頭什么都沒有
(2)輸入http://localhost:8080/index.html,此時出現(xiàn)跨域
? 響應(yīng)頭有Access-Control-Allow-Origin: http://localhost:8080
? 請求頭有Origin: http://localhost:8080
? 表示兩者相同,可以獲取數(shù)據(jù)
(3)輸入http://a.com:8080/index.html 時,就報錯啦
因為服務(wù)端不允許a.com 獲取數(shù)據(jù)
響應(yīng)頭 Access-Control-Allow-Origin 設(shè)置為星號,表示同意任意跨源請求
Access-Control-Allow-Origin: "*"
那么http://a.com:8080/index.html就能獲取數(shù)據(jù)啦!
3?降域iframe里面加載的頁面,它的域名,如果和我當前的是屬于不同域,雖然iframe里面的東西可以加載,但外部的js無法去獲取或操作的。
也就是說,只有在相同域名下的iframe,才可以去訪問里面的東西
舉個例子
a.html
使用降域?qū)崿F(xiàn)跨域
b.html
同樣先是host 文件添加兩條記錄
打開終端,cd 到當前文件夾,啟動http-server
用a.com 打開a.html, http://a.com:8080/a.html , 其中頁面iframe的地址是b.com,和網(wǎng)頁不同源的??梢钥吹皆揻rame可以正確加載,但我們不能用js操作它
用b.com 打開a.html, http://b.com:8080/a.html , 其中frame 的地址是b.com,和網(wǎng)頁同源的,現(xiàn)在我們就可以用 js 獲取 iframe里面的內(nèi)容
當兩個url的主域名不同,但子域名相同的情況下,我們可以通過
注:兩個url的子域名必須相同
舉個例子
a.jrg.com:8080/a.html 和 b.jrg.com:8080/b.html 頁面代碼都加上document.domain = "jrg.com"
在a.html頁面中建一個iframe,通過iframe,兩個js文件即可交互數(shù)據(jù)
a.html
使用降域?qū)崿F(xiàn)跨域
b.html
4?PostMessage允許來自不同源的腳本采用異步方式進行有限的通信,可以實現(xiàn)跨文本檔、多窗口、跨域消息傳遞。
舉個例子 (實現(xiàn)iframe跨域通信)
a.html
使用postMessage實現(xiàn)跨域
b.html
啟動http-server,查看執(zhí)行結(jié)果
總結(jié)一下:
A、a.html 通過 window.postMessage() 發(fā)送一個信息給b.html
B、b.html 在 window 上添加一個事件監(jiān)聽綁定 message 事件,可以接收到來自任何不同域名通過 postMessage 方法發(fā)送過來的信息
C、當 b.html 接收到 a.html 發(fā)送過來的信息時執(zhí)行監(jiān)聽事件就 OK,在監(jiān)聽事件的 event 參數(shù)中包含了所有 message 事件接收到的相關(guān)數(shù)據(jù)。包括發(fā)送信息的內(nèi)容 event.data,發(fā)送信息的域名 event.origin 等等
同樣的,在 a.html 內(nèi)添加一個事件監(jiān)聽綁定 message 事件,在 b.html 內(nèi)通過 postMessage方法發(fā)送信息給 a.html 一樣可以進行跨域通信
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/99930.html
摘要:關(guān)于,強烈推薦閱讀跨域資源共享詳解阮一峰另外,這里也整理了一個實現(xiàn)原理圖簡化版如何判斷是否是簡單請求瀏覽器將請求分成兩類簡單請求和非簡單請求。 前言 從剛接觸前端開發(fā)起,跨域這個詞就一直以很高的頻率在身邊重復(fù)出現(xiàn),一直到現(xiàn)在,已經(jīng)調(diào)試過N個跨域相關(guān)的問題了,16年時也整理過一篇相關(guān)文章,但是感覺還是差了點什么,于是現(xiàn)在重新梳理了一下。 個人見識有限,如有差錯,請多多見諒,歡迎提出iss...
摘要:同源策略所謂同源是指協(xié)議,域名,端口均相同。同源策略是瀏覽器的一個安全功能,不同源的客戶端腳本在沒有明確授權(quán)的情況下,不能讀寫對方資源。需注意的是由于同源策略的限制,所讀取的為跨域請求接口所在域的,而非當前頁。 一、什么是跨域 1.URL解析 URL (Uniform Resource Locator )統(tǒng)一資源定位符(URL)是用于完整地描述Internet上網(wǎng)頁和其他資源的地址的...
摘要:學(xué)習(xí)建議在學(xué)習(xí)其中一種跨域方法的時候,建議邊運行項目里的,邊在網(wǎng)上搜索博客文章學(xué)習(xí)這種跨域方法,這樣有助于快速并且深入理解跨域。鑒于網(wǎng)上有很多文章詳細講述跨域知識,只是少了可以本地運行的,所以這里就不再贅述跨域知識。 前言 因為學(xué)習(xí)跨域需要配置本地服務(wù)器,可能會比較麻煩,所以自己根據(jù)網(wǎng)上的博客寫了大多數(shù)跨域的簡單demo,可以自己在本地運行,而且不用配置服務(wù)器。自己對于跨域的理解剛開始...
摘要:學(xué)習(xí)建議在學(xué)習(xí)其中一種跨域方法的時候,建議邊運行項目里的,邊在網(wǎng)上搜索博客文章學(xué)習(xí)這種跨域方法,這樣有助于快速并且深入理解跨域。鑒于網(wǎng)上有很多文章詳細講述跨域知識,只是少了可以本地運行的,所以這里就不再贅述跨域知識。 前言 因為學(xué)習(xí)跨域需要配置本地服務(wù)器,可能會比較麻煩,所以自己根據(jù)網(wǎng)上的博客寫了大多數(shù)跨域的簡單demo,可以自己在本地運行,而且不用配置服務(wù)器。自己對于跨域的理解剛開始...
摘要:學(xué)習(xí)建議在學(xué)習(xí)其中一種跨域方法的時候,建議邊運行項目里的,邊在網(wǎng)上搜索博客文章學(xué)習(xí)這種跨域方法,這樣有助于快速并且深入理解跨域。鑒于網(wǎng)上有很多文章詳細講述跨域知識,只是少了可以本地運行的,所以這里就不再贅述跨域知識。 前言 因為學(xué)習(xí)跨域需要配置本地服務(wù)器,可能會比較麻煩,所以自己根據(jù)網(wǎng)上的博客寫了大多數(shù)跨域的簡單demo,可以自己在本地運行,而且不用配置服務(wù)器。自己對于跨域的理解剛開始...
摘要:實現(xiàn)跨域的原理通過方式請求載入并執(zhí)行一個文件,相當于通過的形式的導(dǎo)入一個外部的方法語法該函數(shù)是簡寫的函數(shù),等價于在中,您可以通過使用形式的回調(diào)函數(shù)來加載其他網(wǎng)域的數(shù)據(jù),如。將自動替換為正確的函數(shù)名,以執(zhí)行回調(diào)函數(shù)。 更多詳情見http://blog.zhangbing.club/Ja... 最近在項目開發(fā)的過程中遇到一些Javascript 跨域請求的問題,今天抽空對其進行總結(jié)一下,以...
閱讀 2842·2023-04-25 17:21
閱讀 2719·2021-11-23 09:51
閱讀 3027·2021-09-24 10:32
閱讀 3980·2021-09-23 11:33
閱讀 2099·2019-08-30 15:44
閱讀 3587·2019-08-30 11:18
閱讀 3700·2019-08-30 10:53
閱讀 770·2019-08-26 13:25