1. 程式人生 > >iframe跨域通訊的通用解決方案

iframe跨域通訊的通用解決方案

2個信使的情況

一、背景

在這個Web頁面越來越豐富的時代,頁面通過iframe嵌入其他的頁面也越來越常見。但由於瀏覽器同源策略的限制,不同域之間屬性和操作是無法直接互動的,所以在這個時候,開發者多多少少需要一些方案來突破這些限制。跨域問題涉及的地方也很多,如文件之間的訊息通訊、ajax請求、Cookie等,本文討論的是iframe和父頁面的訊息通訊。

二、現狀

目前網上也可以找到各種解決方案(少說都有10+個,有興趣的話可以去看看),對於現代瀏覽器來說,原生的postMessage API一定是不二的選擇,所以各種方案的不同點均在於IE 6、7中的處理(不用相容IE6、7的同志可以去看其他文章了)。當然這麼多方案有各種優缺點,甚至有些只支援單向跨域,個人覺得實際意義不大。另外一些方案需要proxy.html這樣的代理頁面做中轉,但是涉及伺服器上的部署,並且對於多方合作來說還是有些麻煩。

三、思路

雖然不再複述現有的各種方案,但還是想交待一點上下文。相信網上看到最多方案就是利用location.hash或是window.name進行iframe的跨域通訊:

  • location.hash會直接暴露在URL裡,並且在一些瀏覽器裡會產生歷史記錄,資料安全性不高也影響使用者體驗,所以不做考慮。另外由於URL大小的限制,支援傳遞的資料量也不大。
  • window.name相比來講就好很多了,支援2M的資料量,並且當iframe的頁面跳到其他地址時,其window.name值保持不變,副作用可以說是最小的。

講到這思路也比較清晰了,咱們就用window.name唄,但問題又來了:只有兩個頁面同域時才能訪問window.name。這個問題還好,只要把iframe改為與父頁面同域就可以了。這又衍生了新的問題:這不是意味著只能單向通訊了嗎,iframe怎麼向父頁面發訊息(不可能去改父頁面的location吧)?在暗罵坑爹的同時偶然發現了一個很神奇的方法,就是想訪問一個iframe的window.name時,只要將其location改為‘about:blank’即可,屢試不爽~沒錯這個“特性”可以視為IE6/7的一項安全性問題,但利用這個特性來進行跨域通訊並沒有實際的安全風險。

具體的實現見下圖,在iframe的內部再建立一個iframe(我們稱之為信使),父子頁面輪詢信使的window.name,父子頁面各自使用變數儲存window.name,輪詢時發現有變化即被視為收到訊息。基本原理就是這麼簡單,我們繼續..

1個信使的情況

圖1

作為一個通用的解決方案,我們的目標是提供一個js檔案,封裝通訊的介面,需要通訊的頁面只要載入js檔案就行。但在封裝前,需要考慮更復雜一點的情況:當父子頁面雙方頻率較高地雙向通訊時,如何進行支援?按照上述的方案,信使的window.name並沒有讀寫鎖的概念,這意味著訊息很容易亂掉或被漏掉。所以更好的方案應該是:建立兩個信使,分別負責”父–>子”和”子–>父”的訊息傳遞,並且為了防止訊息被沖掉,傳送訊息時會維護一個訊息佇列,在取訊息時處理訊息佇列裡的所有訊息。見圖2。

2個信使的情況

圖2

四、封裝

最後的封裝就是加入了postMessage API的檢測,另外也要判斷是否為跨域,這樣就滿足了所有iframe通訊的情況了。這裡實現的信使只負責訊息的監聽和傳送,所以在使用上是非常簡單的:

1

2

3

4

5

6

7

8

9

10

11

// 父頁面中

// 初始化信使, 告知與其互動的iframe引用

var messenger = Messenger.initInParent(iframeEl);

// 監聽訊息

messenger.onmessage = function (data) {

          ...

};

// 傳送訊息

messenger.send(message);

1

2

3

4

5

6

7

8

9

10

11

// iframe中

// 初始化信使

var messenger = Messenger.initInIframe();

// 監聽訊息

messenger.onmessage = function (data) {

      ...

};

// 傳送訊息

messenger.send(message);

具體使用可以參考下方的demo : )

五、總結

雖然國內也有人提過使用”about:blank”進行iframe通訊的,但是程式碼的封裝和可讀性都不是太好,本方案是一日本人所提出,我覺得處理的很好,所以就拿出來和大家分享下。雖然嘗試過優化輪詢那一塊,但暫時無果,有興趣的朋友可以一起研究下~

DEMO:點選這裡

相關推薦

iframe通訊通用解決方案

一、背景 在這個Web頁面越來越豐富的時代,頁面通過iframe嵌入其他的頁面也越來越常見。但由於瀏覽器同源策略的限制,不同域之間屬性和操作是無法直接互動的,所以在這個時候,開發者多多少少需要一些方案來突破這些限制。跨域問題涉及的地方也很多,如文件之間的訊息

PHP Ajax 問題最佳解決方案

ajax 跨域 域名 -c php文件 解決 tle ron 跨域訪問 客戶端 本文通過設置Access-Control-Allow-Origin來實現跨域。 例如:客戶端的域名是client.runoob.com,而請求的域名是server.runoob.com。 如

.net webapi項目問題及解決方案

prot net 方案 ted access 節點 跨域訪問 架構師資料 eth 問題: 1.項目完成,部署到不同的iis版本上,跨域訪問有的通有的不通 解決辦法: 1.將復雜請求改為簡單請求 2.代碼中去掉所有跨域設置,配置中添加或修改節點 <system

關於ajax的一些解決方案

dst control 關於 請求 method request 進行 前端 請求方式 1、JSONP方式解決跨域問題 jsonp解決跨域問題是一個比較古老的方案(實際中不推薦使用),當然,在實際項目中如果要使用JSONP,一般會使用JQ等對JSONP進行了封裝的

Ajax原理及解決方案

一次 變化 mes iframe 實現 type .ajax 一個 min 跨域請求的產生 跨域請求歸根結底是由於瀏覽器的“同源策略”引起的,同源策略指的是域名相同、協議相同、端口相同, 假設有http://www.a.com/test.html,下面的示例 域名不同 h

PHP ajax問題最佳解決方案

var cell clear 一定的 OS 添加 會有 request TP 一、本文通過設置Access-Control-Allow-Origin來實現跨域。 例如:客戶端的域名是client.runoob.com,而請求的域名是server.runoob.com。 如

PHP Ajax 問題最佳解決方案 【摘自菜鳥教程】

set color ray quest origin tty 所有 $origin con PHP Ajax 跨域問題最佳解決方案 分類 編程技術 http://www.runoob.com/w3cnote/php-ajax-cross-border.html 本文

Access to Image at 'file:///Users canvas本地圖片報錯解決方案

本地服務 canvas 解決方案 圖片 報錯 訪問 can 支持 ESS 1、設置跨域 添加跨域條件 crossorigin="anonymous" 前提是後端支持這個圖片跨域 2、上面加了之後還是報錯   如標題所示  

分享訪問的解決方案與基礎分析

什麼是跨域訪問? 由於瀏覽器同源策略,凡是傳送請求url的協議、域名、埠三者之間任意一個與當前頁面地址不同即為跨域。存在跨域的情況: 網路協議不同,如http協議訪問https協議。 埠不同,如80埠訪問8080埠。 域名不同,如qianduanblog.com訪問baidu.com。

iframe通訊

簡述: window.postMessage方法,允許跨視窗通訊,不論這兩個視窗是否同源。 視窗都可以通過message事件,監聽對方的訊息。 語法: otherWindow.postMessage(message, targetOrigin, [transfer]); messag

.Net平臺下,處理問題CORE解決方案

VS2017 安裝兩個包:Install-PackageMicrosoft.AspNet.WebApi.Cors(如果build不過去還需安裝:Install-Package Microsoft.AspNet.WebApi-IncludePrerelease)  1、 

php 和ajax問題的解決方案

本文通過設定Access-Control-Allow-Origin來實現跨域。 例如:客戶端的域名是client.runoob.com,而請求的域名是server.runoob.com。 如果直接使用ajax訪問,會有以下錯誤: XMLHttpRequest cannot load http://s

JS:1.解決方案之-SpringMVC攔截器

package com.bdqn.utils; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResp

理解及常用解決方案

跨域,相信大家無論是在工作中還是在面試中經常遇到這個問題,常常在網上看到別人所整理的一些方法,看似知道是怎麼回事,但如果沒有動手實踐過,總覺得自己沒有真正的掌握,在這裡,通過自己認真思考整理一些常用的方法。 跨域的產生 不用多講,作為一名前端開發人員,相信大家都知道跨域是因為瀏覽器的同源策略所導致的

Web學習之問題及解決方案

在做前端開發時,我們時常使用ajax與伺服器通訊獲取資源,享受ajax便利的同時,也知道它有限制:跨域安全限制,即同源策略。 同源策略(SOP),核心是確保不同源提供的檔案之間是相互獨立的 預設情況下,XHR物件只能訪問與包含它的頁面處於同一域中的資源,這種限制可以預防某些惡意攻擊,但同

一篇關於ajax問題的解決方案

  這幾天沒事,我有一個好友,讓我幫他做一個機器人對話demo, 我說 看看有沒有時間(其實自己一臉懵逼) 然後百度了一下,發現了一個機器人  -(連線就不弄出來了,可以私底下交流) ,,我是用這個的        

JS請求的解決方案

出現JS跨域請求的原因: 瀏覽器檢測到源的異常 什麼叫做JS跨域: 兩個應用協議,主機地址(域名),埠號。三者有一個不同,則認為他們的域不同。 例如: http:localhost:80/a https:localhost:80/b 此時的a與b的應用協議是不同

到底什麼是?附解決方案

什麼是跨域 要了解跨域,先要說說同源策略。 同源策略是由 Netscape 公司提出的一個著名的安全策略,所有支援 JavaScript 的瀏覽器都會使用這個策略。 所謂同源是指,域名,協議,埠相同。當頁面在執行一個指令碼時會檢查訪問的資源是否同源,如果非同源,那麼

web 專案解決問題終極解決方案

一.跨域問題的由來 二.怎麼就算跨域(同源的定義) 三.常見跨域解決方法 四.總結 一.跨域問題的由來 為什麼會產生這樣一個問題,擺在我們面前呢?? 理解跨域,首先必須要了解同源策略。同源策略是瀏覽器上為安全性考慮實施的非常重要的安全策略。 為了防止某些文件或指令碼載入別

session共享問題解決方案

在討論session跨域共享問題之前,我們首先要了解session做了什麼,沒做到什麼 HTTP是無狀態的,也就是說伺服器不知道誰訪問過他,但是有時候,又需要我們去保留這個狀態比如說使用者的登入資訊,如果每次訪問都要登陸,這個使用者體驗實在是太糟糕了,ses