iframe實(shí)現(xiàn)與父頁(yè)面跨域隔離的JavaScript?代碼沙箱
正文
假如讓你實(shí)現(xiàn)一個(gè)在線的 JavaScript 代碼運(yùn)行環(huán)境,要求用戶代碼不能對(duì)頁(yè)面進(jìn)行修改,以避免潛在的安全問題,你會(huì)怎么做?
使用 with
?使用 proxy
?OK ,都可以,但是這兩種方法都需要關(guān)注很多細(xì)節(jié),否則用戶依舊有可乘之機(jī),這樣一來你的實(shí)現(xiàn)里面就會(huì)有一個(gè)很長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)的操作黑名單。
除此之外,我們還可以專門部署一個(gè)頁(yè)面,將代碼提到服務(wù)端渲染成頁(yè)面,再通過 iframe 去訪問,如果 iframe 與父頁(yè)面之間是跨域的話可以達(dá)到很高的安全性——那么能不能不看后端的臉色,完全使用瀏覽器來實(shí)現(xiàn)類似的沙箱呢?
當(dāng)然可以——
1. iframe
對(duì)前端頁(yè)面而言,跨域是頁(yè)面與頁(yè)面之間的鴻溝,但這并不意味著我們必須重新打開一個(gè)頁(yè)面來運(yùn)行新的代碼,因?yàn)槲覀兛梢允褂?nbsp;<iframe>
標(biāo)簽:
<iframe src="www.xxxx.xxx"></iframe>
對(duì)于同域的 iframe ,我們可以直接通過 .contentWindow
訪問并操作它的全局對(duì)象,然后直接往里面執(zhí)行 JavaScript:
document.querySelector('iframe') .contentWindow .eval('alert("hello world!");');
但是同域頁(yè)面的子頁(yè)面是可以與父頁(yè)面進(jìn)行互操作的,
2. data URL
你可能在一些頁(yè)面里見過小圖片不使用網(wǎng)絡(luò)鏈接,而是采用一個(gè) data:image/png;base64 xxxxxxx
風(fēng)格的 URL ,這種 URL 就是 data URL。
除了 data URL 之外你可能還見過 blob://
開頭的 URL —— Object URL。不過 Object URL 與當(dāng)前頁(yè)面是同域的,而 data URL 與當(dāng)前頁(yè)面是跨域的。所以我們可以在 iframe 使用 data URL 來進(jìn)行跨域隔離。
3. 將 JavaScript 代碼變成 data URL
我們可以直接將 JavaScript 片段變成 data:application/javascript,
的 URL ,但是這樣有一個(gè)問題: iframe 打開這樣的 URL 的時(shí)候,會(huì)顯示代碼原文而不是執(zhí)行代碼,這個(gè)行為其實(shí)和你直接在瀏覽器地址欄輸入 JS 的 URL 是一樣的。
所以我們需要將 JavaScript 代碼拼接到 html
里面,再變成 data URL ,然后交給 iframe 去加載:
const javaScriptFragment = ` alert('hello world'); `; const htmlFragment = ` <!doctype html> <html> <head> <meta chatset="utf-8" /> </head> <body> <script>${javaScriptFragment}</script> </body> </html> `; const dataUrl = `data:text/html,${htmlFragment}`; // 注意,如果代碼片段中含有中文的話,需要使用 encodeURIFragment 轉(zhuǎn)義 htmlFragment document.querySelector('iframe').src = dataUrl;
4. 如果需要獲取執(zhí)行結(jié)果的話,基于 postMessage 定制通信機(jī)制
如果我們不但要做沙箱隔離,還被要求獲取運(yùn)行結(jié)果的話,則可以做一個(gè)通信機(jī)制,讓 iframe 獲取到用戶代碼執(zhí)行結(jié)果, iframe 與父頁(yè)面之間最好的跨域通信方法莫過于 postMessage
。
除了獲取結(jié)果之外,還可以將通信機(jī)制進(jìn)一步擴(kuò)展成為 RPC ,這樣可以實(shí)時(shí)修改頁(yè)面里的代碼來查看效果,類似于 codepen 。
具體實(shí)現(xiàn)與主題不是強(qiáng)相關(guān),這里就不寫了,更多關(guān)于JavaScript iframe頁(yè)面跨域隔離的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
document.compatMode的CSS1compat使用介紹
這篇文章主要介紹了document.compatMode的CSS1compat使用,需要的朋友可以參考下2014-04-04微信小程序頁(yè)面間傳值的實(shí)現(xiàn)方法示例
這篇文章主要給大家介紹了關(guān)于微信小程序頁(yè)面間傳值的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04詳解webpack中的hash、chunkhash、contenthash區(qū)別
這篇文章主要介紹了詳解webpack中的hash、chunkhash、contenthash區(qū)別,詳細(xì)的介紹了hash、chunkhash、contenthash的用法和區(qū)別,有興趣的可以了解一下2018-01-01基于BootStrap Metronic開發(fā)框架經(jīng)驗(yàn)小結(jié)【七】數(shù)據(jù)的導(dǎo)入、導(dǎo)出及附件的查看處理
在很多系統(tǒng)模塊里面,我們可能都需要進(jìn)行一定的數(shù)據(jù)交換處理,這樣可以很好的達(dá)到用戶操作體驗(yàn)感,接下來通過本文給大家介紹基于BootStrap Metronic開發(fā)框架經(jīng)驗(yàn)小結(jié)【七】數(shù)據(jù)的導(dǎo)入、導(dǎo)出及附件的查看處理相關(guān)知識(shí),非常具有參考價(jià)值,感興趣的朋友一起學(xué)習(xí)吧2016-05-05JavaScript 實(shí)現(xiàn)同時(shí)選取多個(gè)時(shí)間段的方法
這篇文章主要介紹了JavaScript 實(shí)現(xiàn)同時(shí)選取多個(gè)時(shí)間段的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10