精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

基于 WebWorker 封裝 JavaScript 沙箱

開發 前端
如果你不知道 web worker 是什么或者從未了解過,可以查看 Web Workers API 。簡而言之,它是一個瀏覽器實現的多線程,可以運行一段代碼在另一個線程,并且提供與之通信的功能。

  [[430837]]

在前文 基于quickjs 封裝 JavaScript 沙箱 已經基于 quickjs 實現了一個沙箱,這里再基于 web worker 實現備用方案。如果你不知道 web worker 是什么或者從未了解過,可以查看 Web Workers API 。簡而言之,它是一個瀏覽器實現的多線程,可以運行一段代碼在另一個線程,并且提供與之通信的功能。

實現 IJavaScriptShadowbox

事實上,web worker 提供了 event emitter 的 api,即 postMessage/onmessage ,所以實現非常簡單。

實現分為兩部分,一部分是在主線程實現 IJavaScriptShadowbox ,另一部分則是需要在 web worker 線程實現 IEventEmitter

主線程的實現

  1. import { IJavaScriptShadowbox } from "./IJavaScriptShadowbox"
  2.  
  3. export class WebWorkerShadowbox implements IJavaScriptShadowbox { 
  4.   destroy(): void { 
  5.     this.worker.terminate(); 
  6.   } 
  7.  
  8.   private worker!: Worker; 
  9.   eval(code: string): void { 
  10.     const blob = new Blob([code], { type: "application/javascript" }); 
  11.     this.worker = new Worker(URL.createObjectURL(blob), { 
  12.       credentials: "include"
  13.     }); 
  14.     this.worker.addEventListener("message", (ev) => { 
  15.       const msg = ev.data as { channel: string; data: any }; 
  16.       // console.log('msg.data: ', msg) 
  17.       if (!this.listenerMap.has(msg.channel)) { 
  18.         return
  19.       } 
  20.       this.listenerMap.get(msg.channel)!.forEach((handle) => { 
  21.         handle(msg.data); 
  22.       }); 
  23.     }); 
  24.   } 
  25.  
  26.   private readonly listenerMap = new Map<string, ((data: any) => void)[]>(); 
  27.   emit(channel: string, data: any): void { 
  28.     this.worker.postMessage({ 
  29.       channel: channel, 
  30.       data, 
  31.     }); 
  32.   } 
  33.   on(channel: string, handle: (data: any) => void): void { 
  34.     if (!this.listenerMap.has(channel)) { 
  35.       this.listenerMap.set(channel, []); 
  36.     } 
  37.     this.listenerMap.get(channel)!.push(handle); 
  38.   } 
  39.   offByChannel(channel: string): void { 
  40.     this.listenerMap.delete(channel); 
  41.   } 

web worker 線程的實現

  1. import { IEventEmitter } from "./IEventEmitter"
  2.  
  3. export class WebWorkerEventEmitter implements IEventEmitter { 
  4.   private readonly listenerMap = new Map<string, ((data: any) => void)[]>(); 
  5.  
  6.   emit(channel: string, data: any): void { 
  7.     postMessage({ 
  8.       channel: channel, 
  9.       data, 
  10.     }); 
  11.   } 
  12.  
  13.   on(channel: string, handle: (data: any) => void): void { 
  14.     if (!this.listenerMap.has(channel)) { 
  15.       this.listenerMap.set(channel, []); 
  16.     } 
  17.     this.listenerMap.get(channel)!.push(handle); 
  18.   } 
  19.  
  20.   offByChannel(channel: string): void { 
  21.     this.listenerMap.delete(channel); 
  22.   } 
  23.  
  24.   init() { 
  25.     onmessage = (ev) => { 
  26.       const msg = ev.data as { channel: string; data: any }; 
  27.       if (!this.listenerMap.has(msg.channel)) { 
  28.         return
  29.       } 
  30.       this.listenerMap.get(msg.channel)!.forEach((handle) => { 
  31.         handle(msg.data); 
  32.       }); 
  33.     }; 
  34.   } 
  35.  
  36.   destroy() { 
  37.     this.listenerMap.clear(); 
  38.     onmessage = null
  39.   } 

使用

主線程代碼

  1. const shadowbox: IJavaScriptShadowbox = new WebWorkerShadowbox(); 
  2. shadowbox.on("hello", (name: string) => { 
  3.   console.log(`hello ${name}`); 
  4. }); 
  5. // 這里的 code 指的是下面 web worker 線程的代碼 
  6. shadowbox.eval(code); 
  7. shadowbox.emit("open"); 

web worker 線程代碼

  1. const em = new WebWorkerEventEmitter(); 
  2. em.on("open", () => em.emit("hello""liuli")); 

下面是代碼的執行流程示意圖

限制 web worker 全局 api

經大佬 JackWoeker 提醒,web worker 有許多不安全的 api,所以必須限制,包含但不限于以下 api

  • fetch
  • indexedDB
  • performance

事實上,web worker 默認自帶了 276 個全局 api,可能比我們想象中多很多。

Snipaste_2021-10-24_23-05-18

有篇 文章 闡述了如何在 web 上通過 performance/SharedArrayBuffer api 做側信道攻擊,即便現在 SharedArrayBuffer api 現在瀏覽器默認已經禁用了,但天知道還有沒有其他方法。所以最安全的方法是設置一個 api 白名單,然后刪除掉非白名單的 api。

  1. // whitelistWorkerGlobalScope.ts 
  2.  
  3. /** 
  4.  
  5. * 設定 web worker 運行時白名單,ban 掉所有不安全的 api 
  6.  
  7. */ 
  8.  
  9. export function whitelistWorkerGlobalScope(list: PropertyKey[]) { 
  10.  
  11. const whitelist = new Set(list); 
  12.  
  13. const all = Reflect.ownKeys(globalThis); 
  14.  
  15. all.forEach((k) => { 
  16.  
  17. if (whitelist.has(k)) { 
  18.  
  19. return
  20.  
  21.  
  22. if (k === "window") { 
  23.  
  24. console.log("window: ", k); 
  25.  
  26.  
  27. Reflect.deleteProperty(globalThis, k); 
  28.  
  29. }); 
  30.  
  31.  
  32. /** 
  33.  
  34. * 全局值的白名單 
  35.  
  36. */ 
  37.  
  38. const whitelist: ( 
  39.  
  40. | keyof typeof global 
  41.  
  42. | keyof WindowOrWorkerGlobalScope 
  43.  
  44. "console" 
  45.  
  46. )[] = [ 
  47.  
  48. "globalThis"
  49.  
  50. "console"
  51.  
  52. "setTimeout"
  53.  
  54. "clearTimeout"
  55.  
  56. "setInterval"
  57.  
  58. "clearInterval"
  59.  
  60. "postMessage"
  61.  
  62. "onmessage"
  63.  
  64. "Reflect"
  65.  
  66. "Array"
  67.  
  68. "Map"
  69.  
  70. "Set"
  71.  
  72. "Function"
  73.  
  74. "Object"
  75.  
  76. "Boolean"
  77.  
  78. "String"
  79.  
  80. "Number"
  81.  
  82. "Math"
  83.  
  84. "Date"
  85.  
  86. "JSON"
  87.  
  88. ]; 
  89.  
  90. whitelistWorkerGlobalScope(whitelist); 

然后在執行第三方代碼前先執行上面的代碼

  1. import beforeCode from "./whitelistWorkerGlobalScope.js?raw"
  2.  
  3. export class WebWorkerShadowbox implements IJavaScriptShadowbox { 
  4.  
  5. destroy(): void { 
  6.  
  7. this.worker.terminate(); 
  8.  
  9.  
  10. private worker!: Worker; 
  11.  
  12. eval(code: string): void { 
  13.  
  14. // 這行是關鍵 
  15.  
  16. const blob = new Blob([beforeCode + "\n" + code], { 
  17.  
  18. type: "application/javascript"
  19.  
  20. }); 
  21.  
  22. // 其他代碼。。。 
  23.  
  24.  

由于我們使用 ts 編寫源碼,所以還必須將 ts 打包為 js bundle,然后通過 vite 的 ?raw 作為字符串引入,下面吾輩寫了一個簡單的插件來完成這件事。

  1. import { defineConfig, Plugin } from "vite"
  2.  
  3. import reactRefresh from "@vitejs/plugin-react-refresh"
  4.  
  5. import checker from "vite-plugin-checker"
  6.  
  7. import { build } from "esbuild"
  8.  
  9. import * as path from "path"
  10.  
  11. export function buildScript(scriptList: string[]): Plugin { 
  12.  
  13. const _scriptList = scriptList.map((src) => path.resolve(src)); 
  14.  
  15. async function buildScript(src: string) { 
  16.  
  17. await build({ 
  18.  
  19. entryPoints: [src], 
  20.  
  21. outfile: src.slice(0, src.length - 2) + "js"
  22.  
  23. format: "iife"
  24.  
  25. bundle: true
  26.  
  27. platform: "browser"
  28.  
  29. sourcemap: "inline"
  30.  
  31. allowOverwrite: true
  32.  
  33. }); 
  34.  
  35. console.log("構建完成: ", path.relative(path.resolve(), src)); 
  36.  
  37.  
  38. return { 
  39.  
  40. name: "vite-plugin-build-script"
  41.  
  42. async configureServer(server) { 
  43.  
  44. server.watcher.add(_scriptList); 
  45.  
  46. const scriptSet = new Set(_scriptList); 
  47.  
  48. server.watcher.on("change", (filePath) => { 
  49.  
  50. // console.log('change: ', filePath) 
  51.  
  52. if (scriptSet.has(filePath)) { 
  53.  
  54. buildScript(filePath); 
  55.  
  56.  
  57. }); 
  58.  
  59. }, 
  60.  
  61. async buildStart() { 
  62.  
  63. // console.log('buildStart: ', this.meta.watchMode) 
  64.  
  65. if (this.meta.watchMode) { 
  66.  
  67. _scriptList.forEach((src) => this.addWatchFile(src)); 
  68.  
  69.  
  70. await Promise.all(_scriptList.map(buildScript)); 
  71.  
  72. }, 
  73.  
  74. }; 
  75.  
  76.  
  77. // https://vitejs.dev/config/ 
  78.  
  79. export default defineConfig({ 
  80.  
  81. plugins: [ 
  82.  
  83. reactRefresh(), 
  84.  
  85. checker({ typescript: true }), 
  86.  
  87. buildScript([path.resolve("src/utils/app/whitelistWorkerGlobalScope.ts")]), 
  88.  
  89. ], 
  90.  
  91. }); 

現在,我們可以看到 web worker 中的全局 api 只有白名單中的那些了。

1635097498575

web worker 沙箱的主要優勢

  • 可以直接使用 chrome devtool 調試
  • 直接支持 console/setTimeout/setInterval api
  • 直接支持消息通信的 api

 

責任編輯:張燕妮 來源: rxliuli blog
相關推薦

2021-12-29 11:38:59

JS前端沙箱

2015-11-12 10:03:34

前端H5web

2016-09-06 21:37:41

2021-04-09 08:51:32

Web WorkerJavaScript微前端

2025-06-12 08:52:18

WebWorkerJSAPI

2017-07-17 06:46:06

2011-05-25 10:21:44

Javascript

2025-03-24 07:15:00

WebWorkerWeb瀏覽器

2025-09-17 18:09:40

WebWorker頁面單線程

2024-03-12 08:44:56

WebWorkerTypeScript語法

2022-04-13 09:28:19

JavaScripiframe開發

2025-07-23 07:16:17

JavaScript隔離開發

2019-02-13 14:58:43

cssjavascript前端

2025-05-29 09:02:27

2025-09-30 09:28:04

JavaScript開發代碼

2025-02-20 12:11:07

WebWorker場景JS

2019-03-22 08:25:47

沙箱網絡安全惡意軟件

2010-09-15 09:03:44

JavaScript

2021-12-29 22:29:10

JavaScript前端數組

2010-08-11 13:46:01

Flex安全沙箱
點贊
收藏

51CTO技術棧公眾號

av动漫在线观看| 亚洲美女性生活视频| 在线观看欧美一区| 亚洲乱码精品久久久久.. | 国产盗摄女厕一区二区三区| 欧美激情中文字幕乱码免费| 欧美一区二区三区成人精品| 欧美大陆国产| 亚洲国产精品一区二区www在线| 欧美人xxxxx| 国产精品一区二区三区在线免费观看 | 久久66热偷产精品| 91av中文字幕| 神马久久精品综合| 九九精品在线| 精品国产乱码久久久久久闺蜜 | 亚洲欧美色图片| 在线观看中文av| 欧美xxx视频| 亚洲国产视频直播| 亚洲一区三区视频在线观看| 午夜性色福利影院| 国产成人在线观看| 国产精品自拍小视频| 欧美日韩精品亚洲精品| 久久国产小视频| 亚洲精品日韩在线| 美女搡bbb又爽又猛又黄www| 日韩深夜福利网站| 欧美午夜精品久久久久久人妖| 久久久久久久久影视| www 日韩| 久久精品人人做人人爽97 | 精品一区二区三区在线| 亚洲福利影片在线| 日本黄色一级网站| 色综合久久久| 欧美日韩国产片| 粗暴91大变态调教| 成人性生交大片免费观看网站| 亚洲精品国产成人久久av盗摄 | 亚洲国产欧美国产综合一区| 久久不射电影网| 男人天堂资源网| 精品国产不卡| 亚洲欧洲激情在线| 欧美狂猛xxxxx乱大交3| 欧美日韩一区二区三区不卡视频| 日韩一区二区三区电影| 五月天视频在线观看| 成人国产精品一区二区免费麻豆 | 国产精品欧美三级在线观看| 亚洲激情在线观看| 好吊色视频一区二区三区| 日韩一级淫片| 精品国产精品网麻豆系列| 九九九久久久久久久| 国产精品免费精品自在线观看| 欧美日韩在线播放| 国产美女视频免费看| 亚洲精品69| 91精品婷婷国产综合久久性色| 五月天激情播播| 国产精品高清一区二区 | 国际av在线| 国产亚洲欧美日韩在线一区| 日韩精品久久一区| eeuss影院www在线播放| 国产精品久久久一本精品| 亚洲欧美日韩在线综合| 久久久久久久久免费视频| √…a在线天堂一区| 青青草综合在线| 国产精品电影| 欧美性做爰猛烈叫床潮| 青青草久久伊人| japanese色系久久精品| 精品视频在线播放免| 国产探花视频在线播放| 在线电影一区二区| 欧美一级大片在线免费观看| 国产伦精品一区二区三区视频我| 麻豆中文一区二区| 97人人香蕉| 日av在线播放| 中文字幕一区免费在线观看| 青青草国产免费| 自拍网站在线观看| 9191精品国产综合久久久久久| 欧美一区二区三区影院| 天美av一区二区三区久久| 亚洲丝袜一区在线| 精品无码久久久久成人漫画 | 国产免费毛卡片| 日本精品网站| 欧美成人性福生活免费看| 欧美 变态 另类 人妖| 日韩精品首页| 欧美精品videossex88| 99re这里只有精品在线| 国产精品一二三四| 日韩国产伦理| 色操视频在线| 在线观看日韩一区| 亚洲熟女乱综合一区二区| 同性恋视频一区| 久久精品国产亚洲精品2020| 日本中文字幕在线免费观看| 喷水一区二区三区| 国产乱码精品一区二区三区日韩精品| 韩国福利在线| 天天影视色香欲综合网老头| 亚洲精品国产久| 亚洲动漫精品| 欧美激情极品视频| 亚洲中文无码av在线| 成人性生交大片免费看中文网站| 先锋影音日韩| 午夜久久中文| 精品播放一区二区| 日韩精品123区| 日韩中文字幕区一区有砖一区| 波多野结衣久草一区| av中文天堂在线| 色综合久久综合网97色综合| 黄色性视频网站| 女人色偷偷aa久久天堂| 国产欧美精品一区二区| 丰满人妻熟女aⅴ一区| 亚洲欧美日韩中文播放| 污视频网址在线观看| 国产一区二区三区91| 欧美精品在线视频观看| 91精品国产综合久久久蜜臀九色| 粉嫩嫩av羞羞动漫久久久| 自拍偷拍视频在线| 成人在线精品| 久久天天躁日日躁| 一区二区三区黄| 国产精品的网站| 国产 欧美在线| 久久99精品久久久久久三级| 男女在线视频| 精品va天堂亚洲国产| 久久这里只有精品免费| 高清av一区二区| 免费视频爱爱太爽了| 51亚洲精品| 欧美精品成人在线| 人妻视频一区二区三区| 午夜国产不卡在线观看视频| 北岛玲一区二区| 亚洲在线成人| 日韩久久精品一区二区三区| 国产v综合v| 少妇激情综合网| 国产精品视频a| 亚洲精品国产无天堂网2021 | 日韩视频在线视频| 久久99国产精品久久99大师| 2019中文字幕在线观看| 你懂得网站在线| 在线观看免费视频综合| 成年人视频软件| 国产精品系列在线播放| 国产无限制自拍| 美女毛片一区二区三区四区| 国产精品美女www| 超碰porn在线| 亚洲国产精品久久精品怡红院| 日韩精品――中文字幕| 久久嫩草精品久久久久| 一区二区三区视频网| 在线成人超碰| 美乳视频一区二区| 国产成人精选| 久久久噜噜噜久久中文字免| 婷婷亚洲一区二区三区| 在线观看91视频| 日韩影院一区二区| av电影天堂一区二区在线观看| 欧美三级一级片| 久久一区二区三区电影| 999视频在线观看| 伊人久久在线| 久久人人爽亚洲精品天堂| 成人免费一级视频| 日本道色综合久久| 欧美久久久久久久久久久久| 久久先锋影音av| xxx中文字幕| 天堂在线亚洲视频| 久久久天堂国产精品| 亚州综合一区| 91在线观看免费网站| 中文字幕21页在线看| www.亚洲天堂| 久草福利在线视频| 日韩欧美www| 中文字字幕在线观看| 亚洲成人精品在线观看| 免费黄色激情视频| 久久伊人蜜桃av一区二区| 手机看片国产精品| 日本不卡高清视频| www国产精品内射老熟女| 欧美成人激情| 欧美动漫一区二区| 国内精品国产成人国产三级粉色| 国产精品久久中文| 免费在线小视频| 久久99精品久久久久久噜噜| 国产www.大片在线| 日韩av综合网| www.五月激情| 7777精品久久久大香线蕉| 黄色免费av网站| 亚洲成人动漫在线观看| √天堂中文官网8在线| 国产精品热久久久久夜色精品三区| 国产美女视频免费观看下载软件| 国内精品伊人久久久久av一坑| 日本久久精品一区二区| 99视频在线精品国自产拍免费观看| 路边理发店露脸熟妇泻火| 97色伦图片97综合影院| 亚洲美女网站18| 国产精品欧美在线观看| 久久精品国产一区二区三区日韩 | 精品国产乱码久久久久久图片| 国产精品-色哟哟| 欧美性xxxxxx少妇| 夜夜爽妓女8888视频免费观看| 天天综合色天天综合| 久久高清免费视频| 亚洲亚洲人成综合网络| 男的操女的网站| 亚洲国产精品二十页| 亚洲午夜精品久久久久久高潮| 国产亚洲欧美日韩日本| 五月天精品视频| 国产欧美日本一区视频| www在线观看免费视频| 久久久久九九视频| 亚洲黄色小说视频| 亚洲国产精品黑人久久久| 国产综合精品久久久久成人av| 国产欧美日韩三级| 1024在线看片| 亚洲色图在线播放| 日本福利片在线观看| 亚洲美女屁股眼交| 欧美精品一区二区蜜桃| 亚洲成av人综合在线观看| 免费在线观看黄网站| 日韩欧美在线第一页| 欧美特级黄色片| 精品视频1区2区| 99国产在线播放| 精品国产乱码久久久久久老虎| 天堂网在线观看视频| 亚洲欧美日韩图片| 69av在线| 欧美区二区三区| 波多野一区二区| 国产激情综合五月久久| 国产精品无码久久久久| 91九色视频在线观看| 精品国内亚洲2022精品成人| 欧美黑人xxxxx| 99久久99视频只有精品| 800av在线免费观看| 性8sex亚洲区入口| 手机免费av片| 成人免费视频app| 免费福利视频网站| 亚洲精品成人少妇| 中文字幕第四页| 欧美一级国产精品| 亚洲欧美日韩动漫| 色婷婷综合久久久久中文字幕1| av片在线观看永久免费| 8x拔播拔播x8国产精品| 日韩黄色碟片| 久久一区二区精品| 婷婷综合久久| 99久久久无码国产精品6| 国内成人免费视频| 性欧美13一14内谢| 亚洲女人小视频在线观看| 天天干天天干天天| 91精品国产91综合久久蜜臀| 亚洲三级中文字幕| 欧美成人中文字幕| 亚洲成人短视频| 国产一区二区三区无遮挡| 久久一区二区三区电影| 成人在线观看你懂的| 久久成人免费网| 在线免费观看麻豆| 夜夜嗨av一区二区三区中文字幕| 无码人妻一区二区三区线| 日韩女优毛片在线| 日本韩国在线视频爽| 538国产精品一区二区免费视频| 大胆国模一区二区三区| 欧美精品v日韩精品v国产精品| 欧美另类综合| 午夜激情av在线| 91蜜桃传媒精品久久久一区二区| 国产高潮流白浆| 在线观看精品一区| 日韩电影免费| 国内揄拍国内精品| 日韩欧美另类中文字幕| 亚洲一区二区三区免费观看| 亚洲尤物影院| 水蜜桃av无码| 亚洲国产一区在线观看| 国产精品视频第一页| 中文字幕精品一区二区精品| 欧美私密网站| 国内精品久久国产| 欧美破处大片在线视频| www.com久久久| 中文天堂在线一区| 老熟妇一区二区三区| 亚洲精品一区二区网址| 蜜桃av在线播放| 精品国产乱码久久久久软件| 韩国久久久久| 国产情侣久久久久aⅴ免费| 亚洲欧美色综合| 国产不卡精品视频| 麻豆国产精品va在线观看不卡| 国产精品麻豆成人av电影艾秋| 欧美一级爽aaaaa大片| 天使萌一区二区三区免费观看| 国产熟妇搡bbbb搡bbbb| 欧美性生交xxxxxdddd| 色中色在线视频| 日本欧美国产在线| 黑丝美女一区二区| 五月天亚洲视频| 国产精品国产精品国产专区不蜜| 依依成人在线视频| www.久久久久久.com| 国产精品视频一区二区三区综合| 中文字幕一区二区三区四区五区人| 麻豆免费精品视频| 国产精品成人69xxx免费视频| 日韩一区二区三区视频在线| 在线观看h网| 国产精品久久久久久久久久久久午夜片 | 亚洲精品福利视频| 成人爱爱网址| 欧美最大成人综合网| 免费成人你懂的| 日本黄色片免费观看| 日韩美女主播在线视频一区二区三区| 欧美巨大xxxx做受沙滩| 国产伦精品一区二区三区视频黑人| 亚洲日产国产精品| 手机看片福利视频| 91精品国产丝袜白色高跟鞋| 污的网站在线观看| 精品伦精品一区二区三区视频| 老司机精品导航| 91成人福利视频| 亚洲国产精品福利| 美女写真久久影院| 日本丰满少妇黄大片在线观看| 成人午夜视频福利| 在线免费观看国产精品| 久热精品视频在线观看| 久久精品66| 成 人 黄 色 小说网站 s色| 亚洲综合色噜噜狠狠| 青春草在线观看| 成人av资源在线播放| 在线成人www免费观看视频| 一级黄色片大全| 日韩一二三四区| 韩国久久久久久| 无码人妻aⅴ一区二区三区日本| 94色蜜桃网一区二区三区| 中文字幕久久久久| 久久久久久中文字幕| av一区二区在线观看| 麻豆av免费看| 欧美午夜一区二区三区| 激情图片在线观看高清国产| 视频二区一区| 成人av网站在线| 国产在成人精品线拍偷自揄拍| 性色av一区二区三区红粉影视| 久久精品播放| 国产精品毛片一区二区| 欧美不卡一区二区三区| 日本综合视频|