iframe是唯一稳妥的沙箱方案,具备独立dom、css和js上下文;应动态创建、用srcdoc内联内容、设sandbox="allow-scripts",禁用eval,处理外链失败与移动端适配。

用 iframe 嵌入沙箱环境最稳妥
直接在当前页面用 document.write 或 innerHTML 注入 HTML 代码会破坏原页面结构、丢失样式作用域,还可能执行恶意脚本。真正安全的演示必须隔离执行环境。iframe 是唯一被浏览器原生支持的轻量级沙箱——它天然具备独立 DOM、CSS 作用域和 JS 执行上下文。
实操建议:
- 动态创建
iframe,设置sandbox="allow-scripts"(禁用表单提交、弹窗等高风险能力) - 通过
iframe.contentDocument.write()写入用户代码,避免跨域限制(同源 iframe 可写) - 不要用
src="about:blank"—— 某些浏览器会触发 CORS 策略;改用srcdoc属性直接内联内容,兼容性更好(Chrome 20+、Firefox 19+、Edge 14+ 支持) - 示例:
<iframe sandbox="allow-scripts" srcdoc="<h1>Hello</h1><script>console.log('run in sandbox');</script>" width="100%" height="200"></iframe>
eval() 和 Function() 在主页面里绝对禁用
有人想“省事”:把用户输入的 HTML 字符串拼进 JS 字符串再 eval() 执行。这等于主动打开 XSS 大门——用户代码能直接读取页面 Cookie、调用 fetch 发送敏感请求、甚至覆盖你自己的事件监听器。
常见错误现象:
- 用户输入
<script>alert(document.cookie)</script>弹出你的登录凭证 - 演示区域空白,控制台报错
Uncaught EvalError: Refused to evaluate a string as JavaScript(CSP 策略拦截) - 页面其他功能突然失效,因为用户 JS 覆盖了全局变量或原型方法
哪怕加了字符串过滤也不可靠——绕过方式太多(onerror=alert(1)、javascript:alert(1)、Unicode 编码等)。别赌自己比攻击者想得全。
处理 CSS 和 JS 加载失败的边界情况
用户粘贴的代码常含外部资源,比如 <link rel="stylesheet" href="https://cdn.example.com/style.css"> 或 <script src="https://unpkg.com/react@18/umd/react.development.js"></script>。这些请求失败时,iframe 不会报错,但渲染结果是白屏或错乱。
可做两件事提升体验:
- 在写入前扫描 HTML 字符串,把
http:///https://的<link>和<script></script>标签临时替换为内联内容(用fetch预加载并注入,注意跨域限制) - 给
iframe绑定onload和onerror,检测是否加载成功;超时 5 秒未完成就显示 “资源加载失败,请检查外链是否可访问” - 禁用用户代码里的
document.write()(在沙箱中重写该函数为空操作),防止它清空整个 iframe 文档
移动端适配和性能卡点
演示区域在手机上缩放失灵、滚动卡顿、字体糊成一片,往往不是 CSS 问题,而是 iframe 默认行为没关掉。
关键配置:
- 给
iframe加width="100%" height="300"并设style="border: none; touch-action: auto;"(否则 iOS Safari 会禁用双指缩放) - 避免在 iframe 内使用
vh单位——Safari 对 iframe 中的视口单位解析异常,改用固定像素或rem - 如果用户代码包含大量 DOM 操作或
setInterval,加个简单超时机制:在 iframe 内注入一段守护脚本,3 秒后若页面仍无响应,自动location.replace("about:blank")清理
真正难的不是让代码跑起来,而是让用户代码跑得“像在真实浏览器里一样”,又不波及你的主站。每个 iframe 都是独立进程,别试图用 JS 主动干预它的内部状态——接受它的不可控性,才是稳定运行的前提。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











