uniapp webview h5 通信 window.postMessage 方式
父頁面
<template>
<view>
<!-- <web-view :webview-styles="webviewStyles" src="https://uniapp.dcloud.io/static/web-view.html"></web-view> -->
<button style="position: absolute;bottom: 20px;z-index: 90000;" @click="evalJs">發送訊息</button>
<view style="padding-top: 20px;">
<web-view ref="webview" src="https://www.cnblogs.com/static/123.html"></web-view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
onLoad() {
},
methods: {
// 呼叫 webview 內部邏輯
evalJs: function() {
// console.log(12);
//通過視窗的 origin 屬性來指定哪些視窗能接收到訊息事件,其值可以是字串"*"(表示無限制)或者一個 URI,在發送訊息的時候,如果目標視窗的協議、主機地址或埠這三者的任意一項不匹配 targetOrigin 提供的值,那么訊息就不會被發送;只有三者完全匹配,訊息才會被發送,這個機制用來控制訊息可以發送到哪些視窗;
//window.frames[0] 注意視窗
window.frames[0].postMessage("hello there!","*")
}
}
}
</script>
<style>
</style>
子頁面
<html>
<head>
</head>
<body>
<script type="text/javascript" src="https://unpkg.com/@dcloudio/[email protected]/index.js"></script>
<div id="io_news" >加載中...</div>
</body>
</html>
<script>
// 接收webView 傳遞的資訊
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
console.log(event);
console.log(event.data);
}
</script>
<script>
//監聽訊息反饋
window.addEventListener('message', (event) => {
console.log("子組件收到訊息:"+JSON.stringify(event.data) + ',' + event.origin)
event.source.postMessage('回復:123456',event.origin)
}, false);
</script>

window.postMessage 【window.postMessage - Web API 介面參考 | MDN (mozilla.org)】
window.postMessage() 方法可以安全地實作跨源通信,通常,對于兩個不同頁面的腳本,只有當執行它們的頁面位于具有相同的協議(通常為 https),埠號(443 為 https 的默認值),以及主機 (兩個頁面的模數 Document.domain設定為相同的值) 時,這兩個腳本才能相互通信,window.postMessage() 方法提供了一種受控機制來規避此限制,只要正確的使用,這種方法就很安全,
從廣義上講,一個視窗可以獲得對另一個視窗的參考(比如 targetWindow = window.opener),然后在視窗上呼叫 targetWindow.postMessage() 方法分發一個 MessageEvent 訊息,接收訊息的視窗可以根據需要自由處理此事件 (en-US),傳遞給 window.postMessage() 的引數(比如 message )將通過訊息事件物件暴露給接收訊息的視窗,
語法
otherWindow.postMessage(message, targetOrigin, [transfer]);
Copy to Clipboard
-
otherWindow其他視窗的一個參考,比如 iframe 的 contentWindow 屬性、執行window.open回傳的視窗物件、或者是命名過或數值索引的window.frames (en-US),
-
message將要發送到其他 window 的資料,它將會被結構化克隆演算法 (en-US)序列化,這意味著你可以不受什么限制的將資料物件安全的傳送給目標視窗而無需自己序列化,[1]
-
targetOrigin通過視窗的 origin 屬性來指定哪些視窗能接收到訊息事件,其值可以是字串"*"(表示無限制)或者一個 URI,在發送訊息的時候,如果目標視窗的協議、主機地址或埠這三者的任意一項不匹配 targetOrigin 提供的值,那么訊息就不會被發送;只有三者完全匹配,訊息才會被發送,這個機制用來控制訊息可以發送到哪些視窗;例如,當用 postMessage 傳送密碼時,這個引數就顯得尤為重要,必須保證它的值與這條包含密碼的資訊的預期接受者的 origin 屬性完全一致,來防止密碼被惡意的第三方截獲,如果你明確的知道訊息應該發送到哪個視窗,那么請始終提供一個有確切值的 targetOrigin,而不是 *,不提供確切的目標將導致資料泄露到任何對資料感興趣的惡意站點,
-
transfer可選是一串和 message 同時傳遞的
Transferable物件,這些物件的所有權將被轉移給訊息的接收方,而發送一方將不再保有所有權,
The dispatched event
執行如下代碼,其他 window 可以監聽分發的 message:
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
// For Chrome, the origin property is in the event.originalEvent
// object.
// 這里不準確,chrome 沒有這個屬性
// var origin = event.origin || event.originalEvent.origin;
var origin = event.origin
if (origin !== "http://example.org:8080")
return;
// ...
}
Copy to Clipboard
message 的屬性有:
-
data從其他 window 中傳遞過來的物件,
-
origin呼叫
postMessage時訊息發送方視窗的 origin . 這個字串由 協議、“??/“、域名、“ : 埠號”拼接而成,例如 “https://example.org(隱含埠443)”、“http://example.net(隱含埠80)”、“http://example.com:8080”,請注意,這個 origin 不能保證是該視窗的當前或未來 origin,因為 postMessage 被呼叫后可能被導航到不同的位置, -
source對發送訊息的視窗物件的參考; 您可以使用此來在具有不同 origin 的兩個視窗之間建立雙向通信,
安全問題
如果您不希望從其他網站接收 message,請不要為 message 事件添加任何事件偵聽器, 這是一個完全萬無一失的方式來避免安全問題,
如果您確實希望從其他網站接收 message,請始終使用 origin 和 source 屬性驗證發件人的身份, 任何視窗(包括例如 http://evil.example.com)都可以向任何其他視窗發送訊息,并且您不能保證未知發件人不會發送惡意訊息, 但是,驗證身份后,您仍然應該始終驗證接收到的消息的語法, 否則,您信任只發送受信任郵件的網站中的安全漏洞可能會在您的網站中打開跨網站腳本漏洞,
當您使用 postMessage 將資料發送到其他視窗時,始終指定精確的目標 origin,而不是 *, 惡意網站可以在您不知情的情況下更改視窗的位置,因此它可以攔截使用 postMessage 發送的資料,
示例
/*
* A 視窗的域名是<http://example.com:8080>,以下是 A 視窗的 script 標簽下的代碼:
*/
var popup = window.open(...popup details...);
// 如果彈出框沒有被阻止且加載完成
// 這行陳述句沒有發送資訊出去,即使假設當前頁面沒有改變 location(因為 targetOrigin 設定不對)
popup.postMessage("The user is 'bob' and the password is 'secret'",
"https://secure.example.net");
// 假設當前頁面沒有改變 location,這條陳述句會成功添加 message 到發送佇列中去(targetOrigin 設定對了)
popup.postMessage("hello there!", "http://example.org");
function receiveMessage(event)
{
// 我們能相信資訊的發送者嗎?(也許這個發送者和我們最初打開的不是同一個頁面).
if (event.origin !== "http://example.org")
return;
// event.source 是我們通過 window.open 打開的彈出頁面 popup
// event.data 是 popup 發送給當前頁面的訊息 "hi there yourself! the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
Copy to Clipboard
/*
* 彈出頁 popup 域名是<http://example.org>,以下是 script 標簽中的代碼:
*/
//當 A 頁面 postMessage 被呼叫后,這個 function 被 addEventListener 呼叫
function receiveMessage(event)
{
// 我們能信任資訊來源嗎?
if (event.origin !== "http://example.com:8080")
return;
// event.source 就當前彈出頁的來源頁面
// event.data 是 "hello there!"
// 假設你已經驗證了所受到資訊的 origin (任何時候你都應該這樣做), 一個很方便的方式就是把 event.source
// 作為回信的物件,并且把 event.origin 作為 targetOrigin
event.source.postMessage("hi there yourself! the secret response " +
"is: rheeeeet!",
event.origin);
}
window.addEventListener("message", receiveMessage, false);
Copy to Clipboard
注意
任何視窗可以在任何其他視窗訪問此方法,在任何時間,無論檔案在視窗中的位置,向其發送訊息, 因此,用于接收訊息的任何事件監聽器必須首先使用 origin 和 source 屬性來檢查訊息的發送者的身份, 這不能低估:無法檢查 origin 和 source 屬性會導致跨站點腳本攻擊,
與任何異步調度的腳本(超時,用戶生成的事件)一樣,postMessage 的呼叫者不可能檢測到偵聽由 postMessage 發送的事件的事件處理程式何時拋出例外,
分派事件的 origin 屬性的值不受呼叫視窗中 document.domain 的當前值的影響,
僅對于 IDN 主機名,origin 屬性的值不是始終為 Unicode 或 punycode; 在使用此屬性時,如果您期望來自 IDN 網站的訊息,則最大程度地兼容性檢查 IDN 和 punycode 值, 這個值最終將始終是 IDN,但現在你應該同時處理 IDN 和 punycode 表單,
當發送視窗包含 javascript: 或 data: URL 時,origin 屬性的值是加載 URL 的腳本的
在擴展非標準中使用 window.postMessage
window.postMessage可用于以 chrome 代碼運行的 JavaScript(例如,在擴展和特權代碼中),但是分派事件的 source 屬性總是為空作為安全限制,(其他屬性具有其期望值,)發送到位于 chrome:URL 的視窗的訊息的targetOrigin引數當前被錯誤解釋,使得將導致發送訊息的唯一值為“*”, 由于此值是不安全的,當目標視窗可以導航到其他地方的惡意網站,建議 postMessage 不用于與 chrome:頁面的溝通; 使用不同的方法(如打開視窗時的查詢字串)與 chrome 視窗進行通信, 最后,在檔案中向頁面發布訊息:URL 當前要求targetOrigin引數為“*”,file://不能用作安全限制; 這個限制可能會在將來被修改,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/509703.html
標籤:其他
上一篇:Sass 筆記
