同事分享一個 Chrome 92 版引發的新問題 - IFrame 內嵌的跨來源網頁將無法呼叫 alert/confirm/prompt。

依據 Chrome 官方資料 - Feature: Remove alert(), confirm(), and prompt for cross origin iframes。原本 Chrome 會在 alert/confirm/prompt 彈出對話框標題註明"某某 URL 顯示",IFrame 內嵌跨站台網頁 alert 則註明"某某 URL 的嵌入式網頁顯示",藉以明確區別,防止 IFrame 內嵌的第三方網頁透過 alert/prompt 偽裝成父網頁從事惡意行為。但由於內嵌跨網站網頁的應用不普遍(一方面也是因為限制愈來愈多,困難重重沒人想用,如今再添一筆),alert/confirm/prompt 這類 JavaScript 原生對話框不再是主流功能,加上 Chrome 覺得"某某 URL 顯示"/"某某 URL 的嵌入式網頁顯示"讓使用者更混淆,便提議禁止 IFrame 內嵌跨站台網頁觸發 alert 等 JavaScript 對話框,此一功能已隨 92 版發佈。

我做了兩個網頁重現問題:

alert.html

<!DOCTYPE html>
<html>
<body>
	<div id=u style='font-size:9pt'></div>
	<script>
		document.getElementById('u').innerText = location.href;
	</script>
	<button onclick="alert('alert from iframe');">Alert</button>
</body>
</html>

alert-parent.html

<!DOCTYPE html>
<html>
<body>
	<div id=u style='font-size:9pt'></div>
	<script>
		document.getElementById('u').innerText = location.href;
	</script>
	<button onclick="alert('alert from parent');">Alert</button>
	<iframe src="http://child.utopia.net/aspnet/iframetest/alert.html"
     style="width:350px;height:60px;margin:10px;display:block">
	</iframe>
</body>
</html>

用上回的模擬方式 parent.utpia.net/alert-parent.html 內嵌 child.utpia.net/alert.hthml 實現跨網站。

改版前 Chrome 的執行結果如下:

改版後,按 IFrame 中的 Alert 鈕將無反應。但主控台會有警示:(A different origin subframe tried to create a JavaScript dialog. This is no longer allowed and was blocked.)

Chrome 目前提供參數 "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-features=SuppressDifferentOriginSubframeJSDialogs 停用此限制(以上測試靠此重現舊版行為),實測 Edge 92 版也已加入這個行為。

Windows 平台修改 Registry 可以停用 Edge 跟 Chrome 的設定:參考

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Edge] 
"SuppressDifferentOriginSubframeDialogs"=dword:00000000
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome] 
"SuppressDifferentOriginSubframeDialogs"=dword:00000000

但依92 版公告,停用選項將在 95 版後移除,亦即未來不行就是不行,也沒開關可以切換了。

If you have any web apps affected by this change, you can use the temporary enterprise policy SuppressDifferentOriginSubframeDialogs to revert to the previous behavior. This policy will be removed in Chrome 95.

但依這幾年的發展,IFrame 內嵌跨網站網頁如過街老鼠,人人喊打,處處受限(例如 X-Frame-Options: SAMEORIGIN 已成標配),如有其他替代方案,能免則免。至於 alert/prompt/confirm 這些古早寫法,建議也儘早用 Bootstrap Dialog、SweetAlert2 取代吧,繼續用只會落得寂寞空虛覺得冷。

Info of Chrome/Edge 92 disabled alert/confirm/prompt from cross-origin page in IFrame.


Comments

# by Jackson28467

最近碰到一個問題,想請教一下。IE 用了一個 cab 元件,會讀取自然人憑證卡。畫面示意: 請輸入PIN碼:______ [確認] 輸入PIN碼按確認,會頓一下等CAB元件回應,請問在這時間點,要怎麼讓確認鈕暫時無作用,因為發現等待 CAB元件回應時,使用者會想去連點。能否讓使用者僅 "能夠" 只按一次確認鈕,謝謝。 有試用 jquery 中的函式 prop('disabled', true) 原本預期流程:用戶點擊→jquery按鈕失效→ CAB元件讀卡。這樣避免用戶連點。 不過實測是:用戶點擊→CAB元件讀卡→jquery按鈕失效。結果在元件讀卡時,用戶還是瘋狂點擊。

# by Jeffrey

to Jackson28467,不是很懂你說的 Cab 元件運作順序,不確定問題關鍵在哪裡,但感覺調一下程式寫法就能避開,能給段 Sample 示意?

# by ChrisTorng

由 https://stackoverflow.com/questions/68505281/chrome-suppressdifferentoriginsubframejsdialogs-setting-override-using-js/68538906#comment121301824_68633707 看到 https://bugs.chromium.org/p/chromium/issues/detail?id=1065085#c41 說,8/15 前暫時取消此限制,之後還是會停用。

# by Jeffrey

to ChrisTorng,感謝補充。(僅暫緩三個星期,真是太高估大型機構的改寫及換版速度惹 XD)

# by Titan

延長到 2022 一月了 https://bugs.chromium.org/p/chromium/issues/detail?id=1065085#c72

# by Jeffrey

to Titan, 謝謝更新。(Google 也懂滾動式修正)

# by ChrisTorng

我猜最後會有如討論中的 <iframe allow="alert">,或者傳 header/讓使用者選擇要不要允許 之類方法,可以不用改寫 alert/prompt/confirm...想裝死的人看要不要繼續撐...

Post a comment