摘要:同源策略在這之前需要先熟悉一下這個概念,同源指請求協(xié)議相同,主機名相同,端口相同,涉及安全的策略。同源策略主要限制的是不同源之間的交互操作,對于跨域內(nèi)嵌的資源不受該策略限制。
問題起因是在使用weibo api的時候,發(fā)現(xiàn)有一個報錯。weibo api是https協(xié)議,我本地是模擬的回調(diào)域名,然后進行數(shù)據(jù)通信,本地http協(xié)議,于是乎就報錯了。出于對postMessage的不是很熟悉,借此機會學習晚上一些自己的知識儲備。
api.weibo.com/2/oauth2/authorize?client_id=******&response_type=token&d…ansport=html5&referer=http://www.unofficial.cn/demo/vuejs/demo.html:1 Failed to execute "postMessage" on "DOMWindow": The target origin provided ("https://www.unofficial.cn") does not match the recipient window"s origin ("http://www.unofficial.cn").同源策略
在這之前需要先熟悉一下這個概念,同源指請求協(xié)議相同,主機名相同,端口相同,涉及安全的策略。
// 例如我的博客地址 http://www.unofficial.cn/demo/postMessage/pm1.html 同 http://www.unofficial.cn/demo/vuejs/index.html 同 https://www.unofficial.cn/demo/postMessage/pm1.html 不同 協(xié)議不同 http://blog.unofficial.cn/demo/postMessage/pm1.html 不同 主機名不同 http://www.unofficial.cn:8080/demo/postMessage/pm1.html 不同 端口不同允許跨域?qū)?/b>
表單提交,例如我模擬了一個表單提交到我的一個其它站點。
同源策略主要限制的是不同源之間的交互操作,對于跨域內(nèi)嵌的資源不受該策略限制。
允許跨域嵌入標簽嵌入腳本,語法錯誤信息只能在同源腳本中捕捉到(?)。
標簽嵌入css
標簽嵌入圖片
和 標簽嵌入多媒體資源
@font-face
載入的任何資源??梢允褂脁-frame-options消息頭來阻止這種形式的交互。
不允許跨域讀需要注意的是,頁面內(nèi)的引入的文件的域并不重要,重要的是加載該文件的頁面所在的域。例如說我在博客的首頁引入了 //cdn.bootcss.com/jquery/3.1.1/jquery.min.js 的jquery文件,這時 jquery.min.js 的源應(yīng)該就是我的博客地址 http://www.unofficial.cn 。
iframe
同域可讀可寫,跨域可讀不可寫
// 請求地址://www.unofficial.cn/demo/postmessage/pm2.html // 不同源時使用contentWindow/contentDocument報錯 // pm1.html:12 Uncaught DOMException: Failed to read the "contentDocument" property from "HTMLIFrameElement": Blocked a frame with origin "http://www.unofficial.cn" from accessing a cross-origin frame.(…)
同源
iframe外部操作,主要通過contentDocument/contentWindow,iframe內(nèi)部使用window.parent,如果只是嵌套了一層可以使用window.top,iframe多層嵌套可以使用window.frameElement
// 外部 -> 內(nèi) var iframe = document.getElementsByTagName("iframe"); // 舉例第一個 iframe[0].contentDocument.getElementById("test").innerText = 123; // 內(nèi)部 -> 外 window.parent.getElementById("test").innerText = 123;
跨域
如果需要在跨域的情況下傳遞參數(shù)怎么操作呢?
iframe內(nèi)部操作,主要通過 location.hash
// 外部傳遞一個123給內(nèi)部 var src = iframe[0].src; iframe[0].src = src.indexOf("#") != -1 ? src.split("#")[0].concat("#", 123) : src.concat("#", 123); // 然后內(nèi)部監(jiān)測hashChange,自動獲取hash值 // 內(nèi)部更改hash window.location.hash = 123; // 但是如何外部如何監(jiān)控src的變化呢?
ajax
cors
同域可讀可寫,跨域請求不能檢查到 Access-Control-Allow-Origin 的情況下會被攔截。
// www.unofficial.cn:4000 // 跨域請求 var url = "http://www.unofficial.cn/demo.php"; var params = "lorem=ipsum&name=binny"; var http = new XMLHttpRequest(); http.open("POST", url, true); http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); http.onreadystatechange = function() { if(http.readyState == 4 && http.status == 200) { alert(http.responseText); } } http.send(params);
> XMLHttpRequest cannot load http://www.unofficial.cn/demo.php. No "Access-Control-Allow-Origin" header is present on the requested resource. Origin "http://www.unofficial.cn:4000" is therefore not allowed access. 上面錯誤提示可以設(shè)置 `Access-Control-Allow-Origin` ,于是在header中添加設(shè)置即可實現(xiàn)跨域請求。
參數(shù)介紹
Access-Control-Allow-Origin
origin參數(shù)指定一個允許向該服務(wù)器提交請求的URI.對于一個不帶有credentials的請求,可以指定為"*",表示允許來自所有域的請求.
Access-Control-Allow-Origin: http://www.unofficial.cn
Access-Control-Allow-Credentials
它的值是一個布爾值,表示是否允許發(fā)送Cookie。默認是 true 允許的。 『實際測試沒發(fā)現(xiàn),也許是方法還不對吧?!?/p>
Access-Control-Expose-Headers
設(shè)置瀏覽器允許訪問的服務(wù)器的頭信息的白名單。如果沒有設(shè)置白名單的,默認情況下只能獲取 Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma的值,沒設(shè)置返回 null,否則會得到以下提示:
Refused to get unsafe header "X-Powered-By"
例如:
// 服務(wù)端設(shè)置 Access-Control-Expose-Headers: X-Powered-By
前端可以這樣獲取到 X-Powered-By 的屬性值
var http = new XMLHttpRequest(); http.getResponseHeader("X-Powered-By"); //
Access-Control-Max-Age
設(shè)置預請求時間。即是設(shè)置 OPTION 的時間。
Access-Control-Allow-Methods
設(shè)置允許的請求方法。
cors的方式可以發(fā)起post請求,或者說其它形式的請求,但是jsonp只能使用get的方式獲取數(shù)據(jù)。
簡單說就是定義好回調(diào)處理方法,把回調(diào)函數(shù)的名稱傳遞給后端,后端拿到數(shù)據(jù)名稱后返回會的數(shù)據(jù)就是對于回調(diào)方法的執(zhí)行。
/** * demo.js的內(nèi)容 * abc({"abc":"123"}); */什么是postMessage
postMessage是window對象的一個屬性,widow.postMessage是一個安全的跨源通信協(xié)議。當且僅當執(zhí)行腳本的頁面使用相同的協(xié)議(通常都是 http)、相同的端口(http默認使用80端口)和相同的 host(兩個頁面的 document.domain 的值相同)時,才允許不同頁面上的腳本互相訪問。 window.postMessage 提供了一個可控的機制來安全地繞過這一限制,當其在正確使用的情況下。
iframe的情況下我們可以這樣使用,等待頁面加載結(jié)束時傳參數(shù)到指定源。
// localhost ① pm1.html頁面中存在一個跨域iframe引用 // www.unofficial.cn pm2.html中我們跨域監(jiān)聽 `message` 獲取 `postmessage` 傳過來的數(shù)據(jù)。
window.open的情況下就需要特殊處理一下了
// localhost ② window.open
延遲多長時間執(zhí)行?頁面加載時間是多長,這個不是很好判斷,setTimeout需要略估計一個時間,待open的頁面加載完成了再postMessage(應(yīng)該不比完全加載就可以postMessage了)。要不然就是定時器,定時推一次,直接觸發(fā)事件后使用window.opener取消定時器。
總結(jié)問題基本都是在過程中發(fā)現(xiàn)一個學習一個,對于沒有太多場景的學習,只能這樣慢慢積累。
參考資料https://developer.mozilla.org...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80815.html
摘要:存在跨域的情況網(wǎng)絡(luò)協(xié)議不同,如協(xié)議訪問協(xié)議。域名和域名對應(yīng)如訪問跨域請求資源的方法代理定義和用法代理用于將請求發(fā)送給后臺服務(wù)器,通過服務(wù)器來發(fā)送請求,然后將請求的結(jié)果傳遞給前端。定義和用法是現(xiàn)代瀏覽器支持跨域資源請求的一種最常用的方式。 1、什么是跨域? 由于瀏覽器同源策略,凡是發(fā)送請求url的協(xié)議、域名、端口三者之間任意一與當前頁面地址不同即為跨域。存在跨域的情況: 網(wǎng)絡(luò)協(xié)議不同,...
閱讀 857·2021-09-22 16:01
閱讀 2125·2021-08-20 09:37
閱讀 1719·2019-08-30 15:54
閱讀 1718·2019-08-30 15:44
閱讀 869·2019-08-28 18:23
閱讀 3042·2019-08-26 12:17
閱讀 1049·2019-08-26 11:56
閱讀 1564·2019-08-23 16:20