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