Quantcast
Channel: WFU BLOG
Viewing all articles
Browse latest Browse all 571

Iframe 跨域傳值在 iOS 失效的解法﹍利用網址 + localStorage + cookie 並用

$
0
0
上一篇「利用隱藏的 Iframe 跨域傳送訊息實作」,很可惜在前端開發人員的大魔王(iOS)面前又失效了,在 iPhone 鬼打牆了很久才瞭解:

  • iOS 禁止 localStorage 跨域傳值
  • iOS 的 Safari 設定中,預設關閉 cookie
  • iOS 的 Chrome 跟一般 Chrome 不太一樣,封鎖了跨域的 localStorage 儲存

除非前端開發人員敢在網頁顯示提示訊息,例如建議「不要使用 iPhone、iPad」、或是「不要使用 Safari」、或是「iPhone 下不要用 Chorme」,否則遲早要面對、解決以上這些狀況。

以下紀錄如何處理這些難題的過程、以及範例程式碼。

(圖片出處: pixabay.com)


一、利用網址傳值


1. Safari 的預設選項

測試 iPhone 裝置的除錯工具,可參考這篇「利用 Chrome 對 iOS 裝置進行除錯(iPhone、iPad)的絕佳方案」。

根據這個討論串「Iframe localStorage on Safari and Safari mobile」,Safari 瀏覽器的設定中,雖然有「允許使用 cookie、允許跨域」的選項,但預設值竟然是關閉的,所以開發人員很可能測試半天也找不出無法跨域的原因。

但就算我們開啟了 Safari 跨域的選項,不代表其他使用者知道要去開啟這個選項,那麼我們做的網頁依然無法使用。


2. 利用網址傳值

還好有看到這篇「localstorage的跨域存储方案」提出了很棒的構想:

  • 利用網址參數傳值

把要傳送的數值放在 Iframe 裡面的網址,當成參數傳遞,就可以完美地繞過 localStorage 與 cookie 的限制!



二、iOS 的 Chrome 跨域問題


利用前述的「網址傳值」技巧,在 iOS 的 Safari,可以成功把跨 Iframe 傳的值,儲存在 localStorage 使用,不過接下來的關卡是 "iOS 的 Chrome"。

很神奇的,Safari 可以把傳過來的值儲存在 localStorage,但 Chrome 竟然無法儲存在 localStorage。說白話一點,iOS 下的 Chrome:

  • 可以儲存任何 localStorage
  • 唯獨 Iframe 跨域網址傳過來的資料,無法存在 localStorage

這個現象實在不知如何解釋,但又不能叫 iOS 使用者不准用 Chrome。

幸好還是發現了解決方法,Safari 預設會封鎖 cookie,但 Chrome 是不會封鎖 cookie 的。所以完美的解法就是,Iframe 用網址跨域傳遞的值:

  • Safari 存在 localStorage
  • Chrome 存在 cookie



三、範例程式碼


以下提供範例:

1. 母視窗

<!--載入 query-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

<!--跨域 IFRAME-->
<iframe id="WFU_frame" src=""></iframe>

<script>
(function($) {
// 網址先編碼
var token = encodeURIComponent("第一筆資料"), // 填入跨域資料
userId = encodeURIComponent("第二筆資料"), // 填入跨域資料
href = "http://demo.wfublog.com/p/cross-domain-postmessage-iframe.html", // 填入跨域網址
search = "token=" + token + "&userId=" + userId, // 網址傳值參數
iframeSrc = href + "?" + search; // 完整 iframe 網址

// iframe 網址傳值
$("#WFU_frame").attr("src", iframeSrc);
})(jQuery);
</script>

修改說明請參照註解文字。


2. Iframe 頁面

<!--載入 jquery cookie-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>

<script>
// 分解網址參數 字串先解碼
var searchSet = decodeURIComponent(window.location.search).substring(1).split("&"),
i, token, userId;

// 從網址找出跨域傳值
for (i in searchSet) {
if (searchSet[i].indexOf("token") === 0) {
token = searchSet[i].split("=")[1];
}
if (searchSet[i].indexOf("userId") === 0) {
userId = searchSet[i].split("=")[1];
}
}

// 跨域傳值寫入 localStorage, for Safari
localStorage.token = token;
localStorage.userId = userId;

// 跨域傳值寫入 cookie, for Chrome
$.cookie("token", token, {
expires: 365,
path: "/"
});
$.cookie("userId", userId, {
expires: 365,
path: "/"
});
</script>

修改說明請參照註解文字。


更多 Javascript 相關技巧:

Viewing all articles
Browse latest Browse all 571

Trending Articles