日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

微前端代碼隔離方案,手把手實現一個 JS 沙箱隔離!

來源: 責編: 時間:2024-07-16 16:59:48 252觀看
導讀今天我們一起來探究一下前端 js 沙箱的核心實現邏輯,我們將從以下幾個方面來展開討論:準備調試環境,探究沙箱需要解決的問題。創建沙箱環境。通過 with 語句改變沙箱變量作用域鏈。通過 proxy 攔截 with 上下文的get,set

今天我們一起來探究一下前端 js 沙箱的核心實現邏輯,我們將從以下幾個方面來展開討論:Gu128資訊網——每日最新資訊28at.com

  1. 準備調試環境,探究沙箱需要解決的問題。
  2. 創建沙箱環境。
  3. 通過 with 語句改變沙箱變量作用域鏈。
  4. 通過 proxy 攔截 with 上下文的get,set操作。

這幾個方面一步一步實現一個簡易的js沙箱。Gu128資訊網——每日最新資訊28at.com

準備調試環境,探究沙箱需要解決的問題:

js沙箱大量應用在微前端框架執行子應用代碼的場景中。我們這里采用最簡單的方式來模擬一下這個場景。Gu128資訊網——每日最新資訊28at.com

我們準備一個js文件,這個js文件的內容就模擬微前端應用基座應用的執行環境,在里面通過 var 定義一個全局變量:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

我們準備兩段字符串,字符串的內容就是js代碼,我們假設這兩段代碼就分別代表了兩個子應用的代碼:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

假如現在微前端框架需要執行子應用1的代碼,那么就會 fetch 子應用1的靜態資源服務器,獲取到類似于 subCode1 這樣的一個代碼字符串。執行子應用2也是同理。那么現在第一個問題來了,怎樣自動執行字符串內部的js代碼?在js中有兩種比較常見的方式:Gu128資訊網——每日最新資訊28at.com

  1. Function:
  2. eval

Function 是js提供的一個內置構造函數,基于它,可以通過字符串,創建出一個js函數,因此我們可以這樣嘗試:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

因為 Function(...)本身就是一個表達式,所以我們可以直接進行調用:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

我們查看一下控制臺:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

可以看到子應用1的代碼就被成功執行了,我們嘗試子應用2的代碼也是同理。Gu128資訊網——每日最新資訊28at.com

eval是js內置的一個函數,這個函數接收一個字符串,eval函數會將這個字符串作為標準的js代碼進行執行:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

我們查看輸出:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

可以看到子應用代碼同樣被正常執行了。 這樣很方便呀,實際上微前端框架內部也是使用類似的方式來執行子應用的js代碼的,但是這樣會有什么問題呢?Gu128資訊網——每日最新資訊28at.com

  1. 目前子應用中的變量定義會污染全局環境:

目前我們在子應用中定義的變量在全局環境中可以直接訪問,所以我們需要調整一下 subCode1 以及 subCode2 兩個子應用的測試代碼:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

我們將兩端子應用的測試代碼包裹到了一個立即執行函數中,這樣子應用內部定義的變量就不會污染全局了。大部分構建工具構建的產物也是這種方式。Gu128資訊網——每日最新資訊28at.com

  1. 在子應用內部可以赤裸裸的訪問 window 對象,并且可以直接對它們進行操作:

圖片圖片Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

我們可以直接在子應用2中通過訪問 window 對象來改變 window 對象的內容。如何攔截子應用直接污染瀏覽器宿主環境的 window 對象是實現js沙箱最核心的問題。Gu128資訊網——每日最新資訊28at.com

創建沙箱環境

我們先編寫一個沙箱構造器函數:Gu128資訊網——每日最新資訊28at.com

var a = 1const sandbox = () => {  return (subCode1) => {       }}

我們編寫了一個高階函數,這個高階函數返回了一個可以接收并且執行子應用代碼的函數。我們期望如果需要執行子應用的結果代碼,只需要這樣進行調用:Gu128資訊網——每日最新資訊28at.com

const box = sandbox()box(子應用1代碼)box(子應用2代碼)box(子應用3代碼)

接下來就是要在高階函數中去編寫執行子應用的代碼了,我們沿著沙箱的需求來思考解決方案。 我們的需求就是屏蔽瀏覽器window對象,為了實現這個需求,我們可以在返回的高階函數中編寫如下的邏輯:Gu128資訊網——每日最新資訊28at.com

const boxCtx = {}return (subCode1) => {  const boxFn = `(function (window) {    ${code}  })(boxCtx)`  // 通過eval函數執行子應用代碼  eval(boxFn)}

實際上就是我們在父函數中創建了一個沙箱的上下文環境,在高階函數中,將子應用代碼放到一個立即執行函數中去進行執行,立即執行函數的參數就是一個window變量,這樣,當我們在子應用代碼內部訪問 window 的時候,因為作用域鏈的原理,就只會訪問到我們在沙箱環境中設置的 window 參數,而無法訪問到瀏覽器全局的 window 對象了。我們可以測試一下:Gu128資訊網——每日最新資訊28at.com

sandbox()('(function() { window.testVal1 = "testVal1"; window.a = 2; })()')console.log(' window.testVal1',  window.testVal1)

圖片圖片Gu128資訊網——每日最新資訊28at.com

這樣做了之后我們就已經可以攔截子應用中對于 window 對象屬性的 set 操作了。 但是如果我們在子應用中嘗試直接通過變量通過 a 來訪問剛剛設置的值的時候,卻是這樣的結果:Gu128資訊網——每日最新資訊28at.com

sandbox('(function() { window.a = 2; console.log("ssss", a); })()')

圖片圖片Gu128資訊網——每日最新資訊28at.com

依然訪問的是全局變量a,原因其實很簡單,因為我們目前構建的沙箱函數內部只有一個 window 變量,并沒有 a 變量。所以js在執行這里的時候只能沿著作用域鏈訪問到全局作用域中的a變量了。要解決這個問題,我們必須確保,我們設置的 window 對象上的所有的屬性全部掛載到沙箱的作用域中。Gu128資訊網——每日最新資訊28at.com

通過 with語句改變沙箱變量作用域鏈:

with 語句的能力可以這樣理解:在js運行時將指定代碼段的執行上下文設置為指定的對象,從而調整該代碼端的作用域鏈。 使用with,我們可以這樣改動并且測試沙箱代碼:Gu128資訊網——每日最新資訊28at.com

const boxCtx = { b: "b" }return (subCode1) => {  const boxFn = `(function boxFn (window) {    with(window) { ${code} }  })(boxCtx)`  // 通過eval函數執行子應用代碼  eval(boxFn)}
sandbox('(function sub1() { window.a = 2; console.log("b", b) })()')

圖片圖片Gu128資訊網——每日最新資訊28at.com

此時 with 語句使得沙箱部分的作用域鏈變成了類似于這樣的結構:Gu128資訊網——每日最新資訊28at.com

sub1(子應用函數上下文) ---> window(with語句設置的代碼上下文) ---> boxFn 函數執行上下文 ---> 全局執行上下文

因此當我們直接在子應用內部訪問 a 變量的時候:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

就可以正常訪問子應用內部設置的全局變量了。Gu128資訊網——每日最新資訊28at.com

但是依然有問題沒有解決,比如我們嘗試執行以下的函數:Gu128資訊網——每日最新資訊28at.com

sandbox('(function() { window.a = 2; window.console.log("ssss", a); })()')

圖片圖片Gu128資訊網——每日最新資訊28at.com

原因其實很簡單,因為此時的沙箱的window對象并沒有 console 屬性,要解決這個問題,我們可以嘗試擴展以下沙箱的上下文的內容,一個很暴力的解法就是:Gu128資訊網——每日最新資訊28at.com

const boxCtx = {    console  }

我們可能會想到一個更加簡單的擴展沙箱上下文的方法:Gu128資訊網——每日最新資訊28at.com

const boxCtx = {    ...window  }

這樣做了之后我們再利用 window.console 來輸出 a 的值:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

為什么會是1呢?如果我們此時在控制臺中訪問一下window.a的值會看到一個更加詭異的現象:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

全局的window的a屬性被修改了。Gu128資訊網——每日最新資訊28at.com

全局window的a屬性被修改的原因其實很簡單,因為瀏覽器宿主的 window 上嵌套了一個 window 屬性,并且這個屬性指向了全局window對象,因此window.window是一個無限嵌套的循環引用:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

正是因為這樣,所以當我們直接使用 ... 淺拷貝一個 window 對象的時候,實際上 嵌套的 window 屬性也就被拷貝過來了,因此此時沙箱上下文是一個類似于這樣的對象:Gu128資訊網——每日最新資訊28at.com

{  ...,  window: {    ...,    window  }}

因此,當沙箱中查找 window 變量的時候是可以直接在 boxCtx 上查找到,而查找的結果就是全局 window 對象的淺拷貝。因此就導致了我們在沙箱內部對于 window 的所有操作實際上操作在了全局window對象上。因此直接拷貝 window 對象來擴展沙箱上下文的方式是不行的。我們得找其他更加簡單的方案。Gu128資訊網——每日最新資訊28at.com

通過 proxy 攔截 with 上下文的get,set操作:

我們可以提出這樣的設想,我們在沙箱內部通過 window.xxx 進行 get 的時候,如果 xxx 在沙箱內部的 window 上存在,那么就直接使用該值,如果不存在,就前往 window 對象上去查找 xxx 的值,這樣是不是就可以解決這個問題了呢?而做到這一步的關鍵就是攔截沙箱上下文的 get 操作,因此首先我們將傳遞給 with 語句的上下文對象變成一個 Proxy 代理對象:Gu128資訊網——每日最新資訊28at.com

const createSandboxCtxProxy = () => {  return new Proxy({}, {    get(target, key, receiver) {          },    set(target, key, value, receiver) {    }  })}const boxCtx = createSandboxCtxProxy()

緊接著可以這樣去攔截 get 和 set 操作:Gu128資訊網——每日最新資訊28at.com

get(target, key, receiver) {      console.log('get', key)      //優先從代理對象上取值      if(Reflect.has(target,key)){         return Reflect.get(target,key);      }      //如果找不到,就直接從window對象上取值      const rawValue = Reflect.get(window,key);      //其他情況直接返回      return rawValue    },    set(target, key, value, receiver) {      return Reflect.set(target, key, value)    },

這樣操作之后我們再次來進行測試:Gu128資訊網——每日最新資訊28at.com

sandbox('(function() { window.a = 2; window.b = "b"; })()')

圖片圖片Gu128資訊網——每日最新資訊28at.com

這樣就達到了和改造之前一樣的效果了,緊接著我們這樣測試:Gu128資訊網——每日最新資訊28at.com

sandbox('(function() { window.a = 2; window.b = "b"; window.console.log("a,b", a, b) })()')

圖片圖片Gu128資訊網——每日最新資訊28at.com

可以看到 console 對象已經可以正常的訪問到了。那么是不是就大功告成了呢?我們再來試一下 window.alert 這類方法:Gu128資訊網——每日最新資訊28at.com

sandbox('(function() { window.a = 2; window.b = "b"; window.alert(`a, b: ${a}, $`) })()')

圖片圖片Gu128資訊網——每日最新資訊28at.com

這個錯誤是因為瀏覽器 window 上的方法在調用的時候函數內部的 this 一定要指向瀏覽器 window 對象。比如我們使用一個更好理解的方式來復原這個錯誤:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

定位到了錯誤的原因,我們就很容易可以解決了,只需要調整 get 方法:Gu128資訊網——每日最新資訊28at.com

get(target, key, receiver) {      console.log('get', key)    //優先從代理對象上取值    if(Reflect.has(target,key)){      return Reflect.get(target,key);    }    //如果找不到,就直接從window對象上取值    const rawValue = Reflect.get(window,key);    //如果兜底的是一個函數,需要綁定window對象,比如window.addEventListener    if(typeof rawValue === 'function'){      const valueStr = rawValue.toString();      if(!/^function/s+[A-Z]/.test(valueStr) && !/^class/s+/.test(valueStr)){        return rawValue.bind(window); // 所有 window 上非構造函數調用時候的 this 綁定window對象      }    }    //其他情況直接返回    return rawValue    },

再次測試:Gu128資訊網——每日最新資訊28at.com

圖片圖片Gu128資訊網——每日最新資訊28at.com

問題已經解決了。至此我們就一步步最簡化的實現了一個js沙箱。Gu128資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-101118-0.html微前端代碼隔離方案,手把手實現一個 JS 沙箱隔離!

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 協方差矩陣適應進化算法實現高效特征選擇

下一篇: 說說MQ延遲隊列實現原理?

標簽:
  • 熱門焦點
  • 鴻蒙OS 4.0公測機型公布:甚至連nova6都支持

    華為全新的HarmonyOS 4.0操作系統將于今天下午正式登場,官方在發布會之前也已經正式給出了可升級的機型產品,這意味著這些機型會率先支持升級享用。這次的HarmonyOS 4.0支持
  • K60 Pro官方停產 第三方瞬間漲價

    雖然沒有官方宣布,但Redmi的一些高管也已經透露了,Redmi K60 Pro已經停產且不會補貨,這一切都是為了即將到來的K60 Ultra鋪路,屬于廠家的正常操作。但有意思的是該機在停產之后
  • 三言兩語說透設計模式的藝術-簡單工廠模式

    一、寫在前面工廠模式是最常見的一種創建型設計模式,通常說的工廠模式指的是工廠方法模式,是使用頻率最高的工廠模式。簡單工廠模式又稱為靜態工廠方法模式,不屬于GoF 23種設計
  • 得物效率前端微應用推進過程與思考

    一、背景效率工程隨著業務的發展,組織規模的擴大,越來越多的企業開始意識到協作效率對于企業團隊的重要性,甚至是決定其在某個行業競爭中突圍的關鍵,是企業長久生存的根本。得物
  • 零售大模型“干中學”,攀爬數字化珠峰

    文/侯煜編輯/cc來源/華爾街科技眼對于絕大多數登山愛好者而言,攀爬珠穆朗瑪峰可謂終極目標。攀登珠峰的商業路線有兩條,一是尼泊爾境內的南坡路線,一是中國境內的北坡路線。相
  • 網紅炒股不為了賺錢,那就是耍流氓!

    來源:首席商業評論6月26日高調宣布入市,網絡名嘴大v胡錫進居然進軍了股市。在一次財經媒體峰會上,幾個財經圈媒體大佬就“胡錫進炒股是否知道認真報道”展開討論。有
  • 消息稱小米汽車開始篩選交付中心:需至少120個車位

    IT之家 7 月 7 日消息,日前,有微博簡介為“汽車行業從業者、長三角一體化擁護者”的微博用戶 @長三角行健者 發文表示,據經銷商集團反饋,小米汽車目前
  • 華為發布HarmonyOS 4:更好玩、更流暢、更安全

    在8月4日的華為開發者大會2023(HDC.Together)大會上,HarmonyOS 4正式發布。自2019年發布以來,HarmonyOS一直以用戶為中心,經歷四年多的發展HarmonyOS已
  • 華為Mate60系列模具曝光:采用碩大圓形后置相機模組+拼接配色方案

    據此前多方爆料,今年華為將開始恢復一年雙旗艦戰略,除上半年推出的P60系列外,往年下半年的Mate系列也將迎來更新,有望在9-10月份帶來全新的華為Mate60
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
欧美aⅴ一区二区三区视频| 在线日韩精品视频| 欧美日本国产在线| 欧美三区视频| 国产三级精品在线不卡| 狠狠色综合色综合网络| 亚洲激情电影中文字幕| 亚洲欧洲在线一区| 亚洲视频在线一区| 久久成人精品电影| 麻豆九一精品爱看视频在线观看免费 | 欧美日韩在线免费观看| 国产女精品视频网站免费| 樱花yy私人影院亚洲| 亚洲免费观看视频| 久久gogo国模裸体人体| 欧美肥婆bbw| 国产精品网站在线观看| 在线成人小视频| 99re6这里只有精品| 久久国产免费看| 欧美经典一区二区三区| 国产目拍亚洲精品99久久精品| 亚洲国产福利在线| 亚洲综合精品自拍| 欧美国产综合视频| 国产亚洲免费的视频看| 日韩一本二本av| 久久国产色av| 欧美日韩综合| 亚洲国产欧洲综合997久久| 亚洲欧美久久久| 欧美欧美午夜aⅴ在线观看| 国产日韩欧美综合| 一本色道久久88精品综合| 久久手机精品视频| 国产精品毛片高清在线完整版| 亚洲国产精品福利| 欧美伊久线香蕉线新在线| 欧美精品国产| 好吊妞**欧美| 欧美一二三区精品| 国产精品a久久久久久| 亚洲第一区色| 久久国产精品高清| 国产精品久久久久久久久免费桃花| 亚洲激情啪啪| 久久久午夜视频| 国产精品一区二区久激情瑜伽| 亚洲人成在线观看网站高清| 久久久久久久一区二区三区| 国产精品久久久亚洲一区 | 国产综合色精品一区二区三区| 亚洲视频播放| 欧美激情亚洲精品| 亚洲高清不卡av| 久久精品五月| 国产视频自拍一区| 午夜免费久久久久| 国产精品美女999| 亚洲视频欧美视频| 欧美日韩成人网| 亚洲精品一二| 欧美国产欧美亚洲国产日韩mv天天看完整 | 亚洲欧洲精品一区二区精品久久久| 久久久久久久97| 国产一区 二区 三区一级| 香蕉乱码成人久久天堂爱免费 | 欧美午夜精品伦理| 一本色道久久综合亚洲精品不卡 | 亚洲精品一区二| 欧美激情bt| 亚洲欧洲精品一区二区三区 | 欧美专区福利在线| 国产日韩在线播放| 欧美在线免费观看亚洲| 国产精品入口尤物| 新67194成人永久网站| 国产欧美日韩综合| 久久精品91| 精品不卡视频| 麻豆国产精品va在线观看不卡| 在线精品视频一区二区三四| 久久综合九色综合久99| 亚洲福利视频一区| 欧美夫妇交换俱乐部在线观看| 亚洲日本va午夜在线电影| 欧美高清在线| 日韩亚洲欧美成人一区| 欧美视频在线看| 亚洲欧美日韩网| 国产区欧美区日韩区| 久久精品91久久香蕉加勒比 | 亚洲人成网站色ww在线| 欧美日韩成人在线观看| 亚洲午夜高清视频| 国产精品在线看| 久久久久久久久久久成人| 一区二区三区在线视频免费观看| 麻豆成人综合网| 亚洲免费黄色| 国产精品久久久久永久免费观看| 性色av一区二区三区| 尤物99国产成人精品视频| 欧美黄色网络| 亚洲一区国产精品| 国产一区二区精品丝袜| 免费视频一区| 国产精品99久久久久久宅男| 国产精品视屏| 久久久噜噜噜久久久| 亚洲三级色网| 国产精品入口66mio| 久久午夜电影网| 日韩视频免费观看高清完整版| 国产精品v欧美精品v日本精品动漫| 亚洲欧美综合国产精品一区| 黄色成人av在线| 欧美日韩成人在线| 久久精品国产精品亚洲综合| 亚洲经典三级| 国产精品视频网址| 卡一卡二国产精品| 这里是久久伊人| 好吊色欧美一区二区三区视频| 欧美久久综合| 欧美在线视频二区| 亚洲经典自拍| 国产精品自拍一区| 免费国产一区二区| 亚洲欧美日韩精品在线| 亚洲福利免费| 国产精品亚洲不卡a| 美日韩丰满少妇在线观看| 亚洲午夜免费福利视频| 激情久久久久久久久久久久久久久久| 欧美乱妇高清无乱码| 久久国产精品久久精品国产| 日韩视频一区二区三区在线播放免费观看| 国产美女一区| 欧美日韩国产va另类| 久久精品欧美| 亚洲视频第一页| 亚洲福利视频专区| 国产乱码精品一区二区三区av| 欧美大胆成人| 久久精品91| 亚洲欧美日韩国产中文在线| 亚洲人久久久| 激情丁香综合| 国产免费亚洲高清| 国产精品视频免费一区| 亚洲一级黄色片| 亚洲精品久久久久中文字幕欢迎你| 欧美一区二区三区啪啪| 欧美日韩国产小视频| 亚洲激情一区二区| 一区二区高清视频在线观看| 久久精品国产999大香线蕉| 欧美激情视频免费观看| 国产精品久久久久永久免费观看| 亚洲国产精品va在线看黑人| 久久精品30| 国产精品一区二区三区四区| 午夜在线电影亚洲一区| 国产伦精品一区二区| 午夜视频一区二区| 国内精品久久久久影院色| 久久精品视频导航| 亚洲二区三区四区| 欧美日韩综合在线| 欧美在线一二三| 欧美激情亚洲另类| 国语自产偷拍精品视频偷| 亚洲欧美中日韩| 亚洲成人资源网| 国产欧美一区二区精品忘忧草| 另类图片国产| 亚洲影视九九影院在线观看| 欧美精品国产精品日韩精品| 一本色道**综合亚洲精品蜜桃冫| 一区二区三区自拍| 国产日韩欧美在线| 欧美精品 国产精品| 久久精品国产亚洲一区二区三区| 亚洲国产影院| 亚洲精品在线二区| 亚洲国产精品专区久久| 国产一级精品aaaaa看| 国产一区激情| 国产一区二区三区在线观看网站| 欧美三级中文字幕在线观看| 美女脱光内衣内裤视频久久影院 | 欧美日韩一区二区国产| 亚洲一区二区在线免费观看视频| 国产精品久久久亚洲一区 | 欧美v日韩v国产v| 亚洲视频在线一区| 欧美日韩一区二区在线观看视频 | 国产午夜精品美女视频明星a级| 国产精品青草久久| 欧美大色视频| 有码中文亚洲精品| 久久精品亚洲一区|